Categories
Lodash

Lodash Array Joining and Filtering Methods We Can Implement Easily

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 implement some Lodash array manipulation methods ourselves, including intersectionBy , last , lastIndexOf , nth , pull , pullAll and join .

intersectionBy

The Lodash intersectionBy method is like the intersection in that it returns an array with the unique entries that are include in all arrays, except that we can pass in our own callback to compare the items our way instead of using the SameValueZero algorithm for comparison.

We can implement it ourselves by taking a callback which we call in the callback of the array instance’s every method as follows:

const intersection = (iteratee, ...arrs) => {
  let vals = [];
  for (const a of arrs[0]) {
    const inAllArrs = arrs.map(arr => arr.map(iteratee)).every((arr) => arr.map(iteratee).includes(iteratee(a)));
    if (inAllArrs) {
      vals.push(a)
    }
  }
  return [...new Set(vals)];
}

In the code above, we get a condition callback function and a list of arrs from the arguments.

Then we get the first array and loops through it. In the loop, we call the every method on arrs to check if each array includes the given item from the first array, which is one of the arrays we want to check.

Also, to check if the item is included or not in every array, we have to map all the entries with the iteratee before checking, including the includes method.

This way, we compare them after they’ve been converted with the iteratee function.

Then, in the end, we converted the added items to a set and then convert it back to an array with the spread operator to return an array with unique items.

join

The Lodash join method converts all elements of an array into a string separated by a separator.

It does the same thing as the plain JavaScript array’s join method except that the plain JavaScript version is called on an array instance. The Lodash join method takes the array as an argument.

For instance, we can implement our own Lodash join method as follows:

const join = (arr, separator) => arr.join(separator)

We can then call it as follows:

const result = join([1, 2, 3], ',')

Then we get result is 1,2,3 .

last

The last method returns the last element of an array. We can easily create our own function to return it as follows:

const last = arr => arr[arr.length - 1]

Then we can call it as follows:

const result = last([1, 2, 3])

And we get that result is 3 as we expected.

lastIndexOf

Lodash’s indexOf method can be implemented easily with the indexOf method in plain JavaScript.

Then we can implement it as follows:

const indexOf = (arr, value, from) => arr.lastIndexOf(value, from)

In the code above, we called the lastIndexOf method with the value we’re looking for and the value that we’re looking for starting from the from index and working towards the beginning.

Then we can call it as follows:

const result = indexOf([1, 2, 3], 2, 3)

and the result is 1.

nth

Lodash’s nth method returns the nth entry in the array. We can obviously implement this easily by getting the n-th entry with the bracket notation as follows:

const nth = (arr, index) => arr[index]

In the code above, we just return the item with the given array index.

Then we can call it as follows:

const result = nth([1, 2, 3], 2)

Then result is 3 since we’re getting the 3rd element.

pull

The Lodash pull method returns a new array with the given values in the array removed.

We can implement it ourselves easily with the filter method as follows:

const pull = (arr, ...values) => arr.filter(a => !values.includes(a))

In the code above, we just called the filter method and in the callback, we call the includes method as we did above to exclude the items that we include with values , which is created by spreading the values.

Then we can call it as follows:

const result = pull([1, 2, 3], 2, 3)

We get that result is [1] .

pullAll

pullAll is similar to pull , except that it takes an array instead of a list of arguments. We can implement it as follows:

const pullAll = (arr, values) => arr.filter(a => !values.includes(a))

Then when we call it as follows:

const result = pullAll([1, 2, 3], [2, 3])

We get the same result value as before.

Conclusion

The join and lastIndexOf methods are built into plain JavaScript, so we can easily use them to implement the Lodash join and lastIndexOf methods.

The nth method gets the nth entry of an array. We can just do that with the bracket notation.

pull and pullAll can easily be implemented with the filter method.

Categories
Lodash

Lodash Array Methods That Can Easily Be Implemented in Plain JavaScript

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 array access methods that can be replaced with plain JavaScript easily.

head

The head method just gets the first element of an array. We can do that without much effort since the first version of JavaScript.

For instance, we can create our own head function as follows:

const head = (arr) => arr[0]

Then we can it as follows:

const result = head([1, 2, 3]);

and get 1 for result .

indexOf

The Lodash indexOf method finds the value from that’s between the first index that we can optionally specify or the beginning of the array and the end of the array.

The plain JavaScript indexOf does the same thing. The only difference is that it’s part of the array instance rather than passing the array into the indexOf method like we do with Lodash.

We can easily use the plain JavaScript’s indexOf method to create our own Lodash’s indexOf method as follows:

const indexOf = (arr, val, start = 0) => arr.indexOf(val, start);

In the code above, we called the plain JavaScript’sindexOf on arr . Then we just pass in val for the item to search for and start for the optional starting index to search for.

Both indexOf methods return the index of the first match. Then we can call it as follows:

const result = indexOf([1, 2, 3], 2, 1);

and we get 1 for result since 2 is in index 1. Both indexOf methods return -1 is the item isn’t found within the range of the index specified.

initial

The Lodash initial method returns all but the last element of the array. We can easily implement this with the slice method.

For instance, we can implement it as follows:

const initial = (arr) => arr.slice(0, -1);

In the code above, we just called since with 0 and -1 as arguments to include the first to the 2nd last element. A negative index starts with -1 from the start to indicate the last element. Then the 2nd last is -2 and so on.

Therefore, when we call it as follows:

const result = initial([1, 2, 3]);

We get [1, 2] as the value of result .

intersection

The Lodash intersection method creates an array of unique values that are included in all the arrays given using SameValueZero equality comparison, which is similar to === except that +0 and -0 are considered different and NaN is the same as itself.

Lodash’s intersection method takes zero or more arrays arguments. We can get all the elements that are in all the arrays as follows:

const intersection = (...arrs) => {
  let vals = [];
  const longestArr = arrs.sort((a, b) => b.length - a.length)[0]
  for (const a of longestArr) {
    const inAllArrs = arrs.every((arr) => arr.includes(a))
    if (inAllArrs) {
      vals.push(a)
    }
  }
  return [...new Set(vals)];
}

In the code above, we first spread the arguments into an array.

Then we loop through the longest array and check if the other arrays have the same entries as the first array with the plain JavaScript’s every method with the callback (arr) => arr.includes(a) , which checks if all the arrays that are passed in include the given entry a .

We don’t have to check all arrays for all entries because if the one we loop through doesn’t have an item, then it shouldn’t be included anyways.

If it’s included in all arrays, then we push it to vals . includes uses the SameValueZero algorithm so that we don’t have to do any other checks for comparison.

Then when we call it as follows:

const result = intersection([1, 2, 3], [1, 2], [1, 3, 5]);

We get [1] as the value of result .

Conclusion

The Lodash head method doesn’t need much effort to implement ourselves since the first version of JavaScript.

The indexOf method can also be easily implemented with the plain JavaScript’s indexOf method.

We can use the slice method to implement the initial method of Lodash.

The intersection method can be implemented by using the spread operator to spread the arguments into an array and then use the for...of loop to loop through the longest array and check if the other arrays have the given entry.

Categories
Lodash

Useful Lodash Array Methods not Available in Plain JavaScript

Even though a few Lodash utility methods have been replaced by built-in methods in plain JavaScript, many still have no equivalent in the JavaScript standard library.

In this article, we’ll look at some Lodash array methods that aren’t in plain JavaScript.

_.take(array, [n=1])

The take method creates a slice of an array from the beginning and returns it.

It takes an array as the first argument and the number of elements n to get from the beginning as the second. n defaults to 1.

For instance, we can use it as follows:

import * as _ from "lodash";

const array = [1, 2, 3, 4, 5];
const arr = _.take(array, 2);

The code above takes the first 2 elements of array , creates a new array and returns it.

Therefore, arr has the value [1, 2] .

If we pass in 0 as the second argument, we get an empty array. If we pass in nothing, we get [1] as the value of arr .

_.takeRight(array, [n=1])

takeRight is like take but creates an array by taking the values starting from the end and returns it.

It takes an array as the first argument and the number of elements n to get from the beginning as the second. n defaults to 1.

For instance, we can use it as follows:

import * as _ from "lodash";

const array = [1, 2, 3, 4, 5];
const arr = _.takeRight(array, 2);

Then arr is [4, 5] because we passed in 2, which takes the last 2 values of array , creates a new array and then returns it.

If we pass in 0 as the second argument, we get an empty array. If we pass in nothing, we get [5] as the value of arr .

_.takeRightWhile(array, [predicate=_.identity])

We can use takeRightWhile top take elements from the end with the given condition and returns it.

Elements are taken until predicate returns a falsy value.

The predicate runs with 3 arguments, which are value , index , and array .

For instance, we can write the following code to extract active users from an array of users:

import * as _ from "lodash";

const users = [
  { user: "foo", active: true },
  { user: "bar", active: false },
  { user: "baz", active: true }
];

const activeUsers = _.takeRightWhile(users, value => value.active);

The code above sets:

[
  {
    "user": "baz",
    "active": true
  }
]

for activeUsers because it takes all the values that have active set to true until it finds one with active set to false .

Therefore, 'baz' meets that condition, so it’s put into the returned array.

On the other hand, the following:

import * as _ from "lodash";

const users = [
  { user: "foo", active: true },
  { user: "bar", active: false },
  { user: "baz", active: false }
];

const activeUsers = _.takeRightWhile(users, value => value.active);

assigns activeUsers to an empty array because the last entry has active set to false , so it never reaches one with active set to true .

Other ways to set predicate includes:

import * as _ from "lodash";

const users = [
  { user: "foo", active: true },
  { user: "bar", active: false },
  { user: "baz", active: false }
];

const inactiveUsers = _.takeRightWhile(users, { user: "baz", active: false });

Which checks the value of user and active in each entry.

Or we can write:

import * as _ from "lodash";

const users = [
  { user: "foo", active: true },
  { user: "bar", active: false },
  { user: "baz", active: false }
];

const inactiveUsers = _.takeRightWhile(users, ["active", false]);

which checks if the active property is false and get those entries.

Or we can write:

import * as _ from "lodash";

const users = [
  { user: "foo", active: true },
  { user: "bar", active: false },
  { user: "baz", active: true }
];

const activeUsers = _.takeRightWhile(users, "active");

to check is active is true .

_.takeWhile(array, [predicate=_.identity])

takeWhile returns a slice of the original array by checking the values from the start.

Elements are taken until predicate returns falsy. The predicate is run with 3 arguments, value , index , and array .

For example, we can write the following code to take values from the users array with active set to true from checking from the beginning of it:

import * as _ from "lodash";

const users = [
  { user: "foo", active: true },
  { user: "bar", active: false },
  { user: "baz", active: true }
];

const activeUsers = _.takeWhile(users, value => value.active);

The code above sets:

[
  {
    "user": "foo",
    "active": true
  }
]

to activeUsers because it checks at the first entry from the start has active set to true , so it takes that one and put it into the returned array.

Then the second has active set to false so it just returns the array with that entry included.

We can also write the following:

import * as _ from "lodash";

const users = [
  { user: "foo", active: true },
  { user: "bar", active: false },
  { user: "baz", active: true }
];

const activeUsers = _.takeWhile(users, { user: "foo", active: false });

to returns all the users entries with user value 'foo' and active set to false .

Likewise, we can write the following:

import * as _ from "lodash";

const users = [
  { user: "foo", active: true },
  { user: "bar", active: false },
  { user: "baz", active: true }
];

const activeUsers = _.takeWhile(users, ["active", true]);

to get all the entries with active set to true until one with active set to false is found.

To make the code even shorter, we can write:

import * as _ from "lodash";

const users = [
  { user: "foo", active: true },
  { user: "bar", active: false },
  { user: "baz", active: true }
];

const activeUsers = _.takeWhile(users, "active");

to make do the same thing as the previous example.

Conclusion

Lodash provides us with many ways to get an array that takes the entries that meet our condition until it finds one that doesn’t meet the condition we set.

These methods have no equivalent in JavaScript’s standard library, but they’re nevertheless useful for many.

Categories
Lodash

Lodash Methods Implemented with Plain JavaScript — Accessing Array Items

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 look at how to implement Lodash array methods that are used to access array items.

findIndex

The findIndex method in Lodash takes an array and then returns the first index of the array item with the given condition.

JavaScript’s standard library already has the findIndex method already. The difference between the Lodash and plain JavaScript version is that the Lodash one can also accept an index for where we can start searching as follows:

const findIndex = (arr, condition, start) => arr.findIndex((a, i) => condition(a) && i >= start)

In the code above, we have our own findIndex method, which takes the following arguments:

  • arr — the original array to call findIndex with
  • condition — the condition to check, which is a callback that takes an array and returns the condition that matches the condition
  • start — which is the starting index of arr to search for items

In the code above, we just called the JavaScript’s built-in findIndex method with a callback that returns the result of condition(a) && i >= start .

This will start searching arr from the start index and the given condition .

Then we can call it as follows:

const index = findIndex([1, 2, 3, 4, 5], a => a > 2, 1)

which means that index should equal 2 since that’s the first array entries that bigger than 2.

findLastIndex

findLastIndex is like findIndex , but searches the array from the end instead of the beginning. The arguments are the same as findIndex except the start index searches towards the beginning instead of the end.

For instance, we can implement it as follows:

const findLastIndex = (arr, condition, start) => {
  for (let i = arr.length - 1; i >= 0; i--) {
    if (condition(arr[i]) && i <= start) {
      return i;
    }
  }
  return -1;
}

In the code above, we implemented the findLastIndex method with a for loop instead of the array’s findIndex method.

If we found the array that meets the condition condition(arr[i]) && i <= start then we return that index since we’re searching from the end towards the beginning for an entry that returns true if we call condition(arr[i]) .

If the loop finished without finding an element, then we return -1. Therefore, when we have:

const lastIndex = findLastIndex([1, 2, 3, 4, 5], a => a > 2, 1)

Then lastIndex is 4 because findLastIndex searches from the end and find one that’s between index 0 and and start .

first

The Lodash’s first method, which is the alias of the head method, takes an array and returns the first entry from it. We can just access the first entry of an array with its index, so we can implement first or head easily as follows:

const first = arr => arr[0]

In the code above, we just use [0] to get the first index of an array.

flatten

Fortunately, there’s already a flat method in plain JavaScript, which can flatten an array by any level.

For instance, we can write the following code to implement Lodash’s flatten , which flattens the given array one level deep:

const flatten = arr => arr.flat(1)

We just called the flat method with 1 to flatten an array one level deep.

Therefore, when we call our flatten function as follows:

const flattened = flatten([1, [2], 3, 4, 5])

We get that flattened is [1, 2, 3, 4, 5] .

Also, we can use the spread operator to implement flatten as follows:

const flatten = arr => {
  let flattened = [];
  for (const a of arr) {
    if (Array.isArray(a)) {
      flattened = [...flattened, ...a];
    } else {
      flattened.push(a);
    }
  }
  return flattened;
}

We looped through the entries of arr and then spread it into a new array if it’s an array. Otherwise, we push to push the entry into the end of the returned array.

Then we get the same result as before.

Conclusion

Lodash’s findIndex can be implemented by the JavaScript array’s findIndex method, which finds the index but we can’t specify what index to start the search with.

To implement the findLastIndex method, we have to use a plain for loop since we have to loop through an array in reverse.

The first method can be implemented by returning arr[0]. Finally, the flatten method can be implemented with the spread operator after we check if the entry is an array with the Array.isArray method. Otherwise, we can use the push method.

Categories
Lodash

Learning JavaScript by Implementing Lodash Methods — Objects and Collections

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 implement methods for checking if something exists in a collection and dealing with objects.

some

The Lodash some method returns a boolean to indicate if an item that meets the condition in the predicate exists in a collection.

For arrays, we can use the plain JavaScript array’s some method to search for an item and returns true is the item with the given condition is found.

We can implement some with the plain JavaScript’s some method as follows:

const some = (collection, predicate) => {
  return collection.some(predicate);
}

In the code above, we just used the array instance’s some method and pass in the predicate .

Then when we run some as follows:

const users = [{
    'user': 'foo',
    'active': true
  },
  {
    'user': 'bar',
    'active': false
  }
];
const result = some(users, u => u.active);

result is true since there’s an entry of users with active set to true .

castArray

The Lodash castArray method converts any object to an array. It takes a list of arguments and puts them all in an array.

With the rest operator, we can put the items in an array without much work. We can implement the castArray method as follows:

const castArray = (...args) => args;

In the code above, we just used the rest operator with args , which converts the list of arguments to an array, and then returned it directly.

Then when we call our castArray function as follows:

const result = castArray(1, 2, 3);

Then we get that result is:

[
  1,
  2,
  3
]

clone

The Lodash clone method returns a shallow copy of an object. It supports cloning all kinds of objects, including arrays, buffers, booleans, and date objects.

Since JavaScript has the spread operator for objects, we can just use that to do the cloning as follows:

const clone = obj => ({
  ...obj
});

Then we can call the clone function as follows:

const result = clone({
  a: 1
});

Then we see that result is:

{
  "a": 1
}

cloneDeep

The Lodash cloneDeep method recursively clones an object. With the spread operator, we can just recursively clone each level of an object ourselves.

For instance, we can implement that as follows:

const cloneDeep = (obj, cloned = {}) => {
  if (Array.isArray(obj)) {
    cloned = [
      ...obj
    ];
    for (let i = 0; i < obj.length; i++) {
      cloneDeep(obj[i], cloned[i]);
    }
  } else if (typeof obj === 'object') {
    cloned = {
      ...obj
    };
    for (const p of Object.keys(obj)) {
      cloneDeep(obj[p], cloned[p])
    }
  }
  return cloned;
}

In the code above, we have our own cloneDeep function, which takes obj for the original object and the cloned object which has the cloned object.

We loop through the objects and call cloneDeep on them afterward.

If obj is an array, then we spread the array with the spread operator.

Otherwise, we can use the spread operator to clone obj into cloned at the top level.

Then we check that if obj is an object. If it is, then we can loop through the keys and calls cloneDeep in the lower level of an object.

In the end, we return cloned with the cloned object.

Then we can call our cloneDeep function as follows:

const obj = {
  a: 1,
  b: {
    c: 2
  }
}
const result = cloneDeep(obj);

Then we get that result is:

{
  "a": 1,
  "b": {
    "c": 2
  }
}

and:

result === obj

is false . We can also clone arrays as follows:

const obj = [{
  'a': 1
}, {
  'b': 2
}]
const result = cloneDeep(obj);

Then we get that result is the following array:

[
  {
    "a": 1
  },
  {
    "b": 2
  }
]

and:

result === obj

is still false .

Conclusion

We can use the plain JavaScript array’s some method to check if an object that meets the condition in a predicate exists in a collection.

To implement the castArray method, we can just use the rest operator on the arguments.

Finally, the clone and cloneDeep methods can be implemented with the spread operator. cloneDeep needs an array or object check before cloning each level.