Categories
Lodash

Learning JavaScript by Implementing Lodash Methods — Diffing and Zipping

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 some methods to get the symmetric difference and zipping arrays.

xorBy

The xorBy method returns the symmetric difference of multiple arrays, which is an array without the entries that appear in all the arrays.

It does that by first running an iteratee function before doing the comparison. The iteratee function takes one argument to map a given entry to something else.

We can do that as follows:

const xorBy = (iteratee, ...arrs) => {
  const symDiff = [];
  for (const arr of arrs) {
    for (const a of arr) {
      const inAllArrays = arrs.every(arr => arr.map(iteratee).includes(iteratee(a)));
      if (!inAllArrays) {
        symDiff.push(a);
      }
    }
  }
  return symDiff;
}

In the code above, we used the rest operator to spread the arrays argument into an array of arrays.

Then we used the every method that’s in plain JavaScript to see if an entry is in all the arrays in our for...of loop.

When doing the comparison, we call map first with the iteratee function, then we also call iteratee when calling includes so that we’re comparing the mapped values instead of the original values.

Then if it’s not in the original array, then we put it in the symDiff array.

When we call it as follows:

const result = xorBy(Math.floor, [2.1, 1], [2.2, 3])

We get that result is [1, 3] because we mapped the values with Math.floor before comparing, so 2.1 and 2.2 are considered the same and are in all the arrays.

xorWith

xorWith is similar to xorBy in that, it runs a function. The difference is that the function is used to compare the values instead of mapping the values before comparing the items.

We can implement it similar to xorBy as follows:

const xorWith = (comparator, ...arrs) => {
  const symDiff = [];
  for (const arr of arrs) {
    for (const a of arr) {
      const inAllArrays = arrs.every(arr => arr.findIndex(b => comparator(a, b)) >= 0);
      if (!inAllArrays) {
        symDiff.push(a);
      }
    }
  }
  return symDiff;
}

In the code above, we used the every method like we did with xorBy , but we called findIndex with comparator inside to compare the values to determine if they’re in all the arrays.

If they’re not then we push them into the symDiff array. In the end, we return it.

Then when we call it as follows:

const result = xorWith((a, b) => Math.floor(a) === Math.floor(b), [2.1, 1], [2.2, 3])

We get tat result is:

[
  1,
  3
]

zip

The Lodash zip method groups elements, with the first elements of each array in the first array, the second element of each array in the second array, and so on.

We can do that we for loops as follows:

const zip = (...arrs) => {
  let zipped = [];
  for (let i = 0; i < arrs[0].length; i++) {
    if (!Array.isArray(zipped[i])) {
      zipped[i] = [];
    }
    for (const arr of arrs) {
      zipped[i].push(arr[i]);
    }
  }
  return zipped;
}

In the code above, we used the rest operator to spread the arrs argument into an array of arrays.

Then we loop through the items with a for loop and inside it, we check that if zipped[i] isn’t an array, then we create an array.

Once we did that we loop through the arrays in arrs with the for...of loop and get the array entry in the position i of each array and push it into the arrays in zipped array in the same position.

Then when we call zip as follows:

const result = zip(['a', 'b'], [1, 2], [true, false])

We see that result is:

[
  [
    "a",
    1,
    true
  ],
  [
    "b",
    2,
    false
  ]
]

Conclusion

We can get the symmetric difference in different ways with Lodash either by mapping the values with an iteratee function or by comparing them with the conparator function.

To zip an array of arrays, we create a new array by first creating a new array of arrays, then we push each entry of the original nested array in the given position into the new nested array in the same position.

Then we return that array.

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 *