Categories
Lodash

Plain JavaScript Versions of Lodash Methods to Slice and Join Arrays

Spread the love

Lodash is a very useful utility library that lets us work with objects and arrays easily.

However, now that the JavaScript standard library is catching up to libraries such as Lodash, we can implement many of the functions in simple ways.

In this article, we’ll look at how to replace the takeWhile , union , unionBy and unionWith with plain JavaScript code.

takeWhile

takeWhile is a reverse of takeRightWhile . It returns the slice of an array with elements taken from the beginning until the predicate function with the given array entry returns true .

We can easily implement this ourselves with slice as follows:

const takeWhile = (arr, predicate) => {
  let takenArr = [];
  for (const a of arr) {
    if (!predicate(a)) {
      takenArr.push(a);
    } else {
      return takenArr;
    }
  }
  return takenArr;
}

In the code above, we used the for...of loop to loop through the entries and returns takenArr if predicate(a) returns true .

We also return takenArr if the loop finishes if predicate(a) never returns true .

Then when we call it as follows:

const result = takeWhile([30, 40, 50], a => a > 40);

We get that result is [30, 40] since we specified we stop if an element if bigger than 40.

union

The union method returns a new array with unique values from multiple arrays in order using the SameValueZero equality comparison.

We can implement it ourselves with the spread operator as follows:

const union = (...arrs) => {
  return arrs.reduce((arr1, arr2) => [...new Set([...arr1, ...arr2])])
}

In the code above, we called reduce on arrs with a callback that returns the unique values of the 2 arrays spread with spread operator. The new array is then converted to a set and then converted back to an array with the spread operator.

Then we can call it as follows:

const result = union([30, 40, 50], [30, 60]);

and result is [30, 40, 50, 60] since the values from the earlier arrays are kept and then the later ones that aren’t already in the accumulated array is added.

unionBy

The unionBy method returns an array with the unique items in each array. The difference between this and union is that unionBy lets us pass in a method to map the values before doing the uniqueness comparison.

We can implement it as follows:

const unionBy = (iteratee, ...arrs) => {
  let unionArr = [];
  for (const arr of arrs) {
    const mapped = arr.map(iteratee);
    const unionMapped = unionArr.map(iteratee);
    const uniques = mapped.filter(a => !unionMapped.includes(a));
    unionArr = [...unionArr, ...uniques];
  }
  return unionArr;
}

In the code above, we have the iteratee as the first argument instead of the last so that we can use the rest operator with arrs to return an array of the array arguments passed in after the iteratee function.

Then we have a for...of loop to loop through the items and inside the loop, we map the arr entries with the iteratee function.

Also, we mapped the unionArr array with the same function so that we can use the includes method with filter to get the entries that aren’t unionArr yet after comparing it after converting the values with iteratee .

Then when we call it as follows:

const result = unionBy(Math.floor, [30.1, 40, 50], [30.2, 60]);

We get [30, 40, 50, 60] for result since we mapped the values in all arrays with Math.floor before doing a comparison.

unionWith

unionWith is like union except that it accepts a comparator to compare the elements and pick the first one that is unique.

We can implement our own unionWith function as follows:

const unionWith = (comparator, ...arrs) => {
  let unionArr = [];
  for (const arr of arrs) {
    const uniques = arr.filter(a => !unionArr.find(u => comparator(a, u)));
    unionArr = [...unionArr, ...uniques];
  }
  return unionArr;
}

In the code above, we looped through arrs with a for...of loop. Inside the loop, we called filter on arr to return an array with the ones that aren’t in the unionArr array and assign the array to the uniques constant.

Then we spread the values of the existing unionArr array and the uniques array and then assign that new array to unionArr .

Finally, we return unionArr . Then when we call it as follows:

const result = unionWith((a, b) => Object.is(a, b), [30, 40, 50], [30, 60]);

We get that result is [30, 40, 50, 60] since we compared the values with Object.is to determine if they’re unique or not.

Conclusion

The union , unionBy , and unionWith methods can be implemented with the spread operator and using array’s filter method.

takeWhile can be implemented with the for...of loop and checking for the given predicate in each iteration.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *