Skip to content

lodash

Created: 2017-03-14 11:10:01 -0700 Modified: 2023-05-02 17:33:58 -0700

  • For a TypeScript-focused equivalent library, check out Remeda.
  • To find out about future Lodash plans, including which APIs are planned to be deprecated, check out the roadmap

Just use plain JavaScript for this. For example, let’s say we want to sort coordinates ascending first by their X and then by their Y values:

Coordinates may look like [[2,5], [2,3], [4,5], [7,2], [9,9], [5,4], [6, 1]]

coords.sort(([x1, y1], [x2, y2]) => {
if (x1 === x2) return y1 - y2;
return x1 - x2;
});

“coords” will now contain [[2,3], [2,5], [4,5], [5,4], [6,1], [7,2], [9,9]]

orderBy on an array with multiple orders

Section titled orderBy on an array with multiple orders

Suppose you have an array of intervals each denoted by [start, end], meaning your array may look like this:

[ [1, 40], [20, 30], [1, 39], [5, 500], ]

If you want to sort by ascending “start” values followed by descending “end” values, you could use this code:

const sortedIntervals = _.orderBy(
intervals,
[([start, end]) => start, ([start, end]) => end],
["asc", "desc"]
);

This is because orderBy allows for an array of functions to be passed in.

Note that ”([start, end]) => start” is destructuring the array into its constituent elements. We could also have done this:

(arr) => arr.start

Suppose you have something like this:

var users = [
{ id: 1, age: 48 },
{ id: 2, age: 34 },
{ id: 3, age: 40 },
{ id: 4, age: 36 }
];
users = _.orderBy(users, ["age"], ["desc"]);
const index = _.sortedIndexBy(users, { age: 42 }, user => user.age);
console.log(users);
console.log("index: " + JSON.stringify(index));
[ { id: 1, age: 48 },
{ id: 3, age: 40 },
{ id: 4, age: 36 },
{ id: 2, age: 34 } ]
index: 4

What’s happening above is that we’re sorting users by age (descending) and getting the correct sorted value. However, the index at which we try to insert a person whose age is 42 is the end of the array (which is wrong). This is because sortedIndexBy expects the input to be in ascending order.

To fix this, we can negate the values in sortedIndexBy:

const index = _.sortedIndexBy(users, { age: 42 }, user => -user.age);

What this essentially does is treats the array like it was in ascending order when it comes time to compare, so keep in mind that this won’t work for string values where you can’t easily negate the comparison. For those, you’d have to either _.reverse the array or write your own binary search.

Using reduce to accumulate an array (AKA “map with multiple additions”)

Section titled Using reduce to accumulate an array (AKA “map with multiple additions”)

Suppose you had a bunch of users and you wanted their first and last names individually in an array, e.g. [‘John’, ‘Doe’, ‘Mary’, ‘Smith’].

You can do that this way:

const firstAndLastNames = _.flatten(_.map(users, (user) => [user.firstName, user.lastName]));

However, that involves a flatten.

You can use reduce to do the same thing:

_.reduce(users, (accum, user) => {
accum.push(user.firstName);
accum.push(user.lastName);
return accum;
}, []);
const names = ["A", "B", "C"];
const objs = _.reduce(names, (accum, name) => {
accum[name] = true;
return accum;
}, {});

Result:

{A: true, B: true, C: true}

Check if array only has elements of the type you expect

Section titled Check if array only has elements of the type you expect

E.g. check array for all numbers:

[1, 5, 7] ==> true

[1, 5, ‘Adam’, 7] ==> false

_.every(array, _.isNumber);

Note that if you find yourself doing something like this often where you’re validating types of things, consider using Joi.

// To do this with a custom value, use this:

function createArray(length, value) {

_.times(length, () => value)

}

// To do this with numeric values, use this:

_.range(0, 5, 0) ==> [0,0,0,0,0]

If you’re filling an array with a primitive, then you can use “_.fill(Array(COUNT), value)“.

If you’re filling an array with a new object, then you don’t want all of the references to be to the same instance, so you can do this

Array(x).fill(0).map(() => new Bucket)

^— note: that doesn’t use Lodash, but it’s the same general principle.

Removing the first instance of a specific element from an array

Section titled Removing the first instance of a specific element from an array

Apparently Lodash hasn’t added a specific function for this as of 3/14/2017, so you should do this instead:

// Note: you could also just use "indexOf" if you know you have an array and bypass Lodash altogether
const userIndex = _.findIndex(users, (user) => userId === user.getId());
if (userIndex !== -1) {
users.splice(userIndex , 1);
}

Ensuring an object only contains “allowed” properties

Section titled Ensuring an object only contains “allowed” properties

I found that the best way to do that is to just use pick:

export function ensureObjectOnlyHasSpecificKeys(object, allowedKeys) {
const pickedPaths = _.pick(object, allowedKeys);
return _.size(pickedPaths) === _.size(_.keys(object));
}

Ensuring an object contains only/all keys specified by another object

Section titled Ensuring an object contains only/all keys specified by another object

For example, suppose you have this:

const colors = {
'red': 'RED',
'green': 'GREEN'
};
const colorCodes = {
[colors.red]: '#ff0000',
[colors.green]: '#0000ff'
};

You want to make sure colorCodes contains ONLY codes from ‘colors’ and matches all of the codes from ‘colors’:

assert(
_.isEqual(
_.orderBy(_.keys(colors)),
_.orderBy(_.keys(colorCodes))
)
);