DEV Community

Amruth Pillai
Amruth Pillai

Posted on

Recreating Lodash: _.pull()

I want to start a series where I'll look at various lodash functions and recreate them to the best of my knowledge using plain ol' Javascript.

I did look around for this on DEV, but couldn't find any articles related to this, so saw an opportunity to make one (or maybe I'm just really bad at searching).

I'm starting out with the _.pull() function cause that's one I know how to recreate easily, but feel free to suggest functions in the comments below and I'll consider them for the next edition of the series.

What does it do?

The _.pull() method simply takes an array and a variable number of values after it and modifies the array with the values removed.

let array = ['a', 'b', 'c', 'a', 'b', 'c'];
_.pull(array, 'a', 'c');
console.log(array);
// => ['b', 'b']
Enter fullscreen mode Exit fullscreen mode

How can we make it better?

Now, if there's one thing I do not like, it's functions mutating my original array. I'd much rather have it return a new array thus not modifying the original data.

Another change I'll be making is instead of working on variable arguments, to make this tutorial simple, I'll just pass another array with all the values, so the finished function would look like this:

array = ['a', 'b', 'c', 'a', 'b', 'c'];
result = pull(array, ['a', 'c']);
console.log(result);
// => ['b', 'b']
Enter fullscreen mode Exit fullscreen mode

This is similar to another function in lodash, _.difference(), so we're essentially rebuilding that.

How do we build it?

Right off the bat, we'll be using the Array.prototype.filter() method for this.

Let's write our function definition first.

let pull = (array, values) => {
  // insert magic here
};
Enter fullscreen mode Exit fullscreen mode

Let's call the filter method on the array.

let pull = (array, values) => {
  return array.filter(item => {
    // insert more magic here
  })
};
Enter fullscreen mode Exit fullscreen mode

Now, we're going to check if the item inside the values array exists inside the array. We can do this by using the Array.prototype.indexOf() function.

If the value exists, we would get a non-zero value, so we can return false to remove it from the array, otherwise we can return true to keep it in the array.

let pull = (arr, values) => {
  return arr.filter((item) => {
    return values.indexOf(item) < 0;
  });
};
Enter fullscreen mode Exit fullscreen mode

This is going to churn out our expected output.

Does this really work?

Here's a CodePen to play around with and see the code in action.

Conclusion

Of course, in reality, lodash does a lot more in terms of type checking and it's well built out, but it would pay to know how it works under the hood :)

Do let me know if you find this interesting with a reaction, and if you want to see other functions, mention them in the comments!

Thank you so much for reading! :)

Top comments (1)

Collapse
 
miketalbot profile image
Mike Talbot ⭐

Hey I like the idea of this article, but I do have a couple of comments:

  • The execution time of your function is heavy if values is large, basically making the execution time O(array.length * values.length). An O(array.length) implementation might look like:
function pull(array, values) {
    const inclusion = new Set(values)
    return array.filter(value=>!inclusion.has(value))
}
  • I find it odd to declare a top level function as a "fat-arrow". It's building something to capture global this and that's wasteful. It requires that you declare functions in sequence, which can become a pain and it's just not clear to me that a const is a function - plus who knows how this gets highlighted - but code pen didn't work out it was a function.

  • Making new arrays all the time has a significant impact on memory and execution time through garbage collection. I get immutability is an important style for reducing complexity, but sometimes it worries me to hell when a developer is taking a temporary array from the previous step and making yet another one.