Lodash, find indexes of all matching elements

Viewed 11347

Using lodash, how to get the array of indexes of all matching elements? As example:

Animals = [{Name: 'Dog', Id: 0},
          {Name: 'Cat', Id: 1},
          {Name: 'Mouse', Id: 2},
          {Name: 'Horse', Id: 3},
          {Name: 'Pig', Id: 3}]

And then I want to find indexes of all elements with Id == 3.

Expected output:

Indexes = [3,4];
6 Answers

Here is a short solution:

Indexes = _.keys(_.pickBy(Animals, {Id: 3}))

output:

Indexes = ["3", "4"]

Use pickBy to pick element, and keys to get indexes.

pickBy is for object

_.pickBy(object, [predicate=_.identity])

Creates an object composed of the object properties predicate returns truthy for. The predicate is invoked with two arguments: (value, key).

https://lodash.com/docs/4.17.10#pickBy

But when use on array, it return a object like

{
  3: {Name: "Horse", Id: 3},
  4: {Name: "Pig", Id: 3}
}

use _.keys on this object to get all keys in string array

["3", "4"]

If you want to get number array, use _.map

_.map(_.keys(_.pickBy(Animals, {Id:3})), Number)

You will get

[3, 4]

Another solution:

_.filter(_.range(animals.length), (i) => animals[i].id === 3);

id === 3 is the filter condition defined in the question above.

_.filter(
  _.map(Animals, (animal, index) => animal.id === 3 ? index : -1), 
  (index) => index >= 0
)

edit: animal.id === 3 is the filter condition defined in the question above.

That's what reduce is for:

_.reduce(Animals, function(result, value, key) {
          if(value.Id == 3) result.push(key);
 }, {});

You can use the @AliYang answer with chain and for me, it looks more readable:

const findAllIndexes = <T>(array: Array<T>, predicate?: ValueKeyIteratee<T>) => {
  return chain(array)
    .pickBy(predicate)
    .keys()
    .map(Number)
    .value();
}

This implementation is with TS and the ValueKeyIteratee type comes from lodash, you can see it is used by lodash's pickBy

Related