7

I have an array of objects which I would like to filter using a contains/any method on a property using underscore.

For example, if I had the following variables:

var people = [
{
    name: 'Dave',
    age: 26
},
{
    name: 'Frank',
    age: 23
}];
var allowedAges = [20, 23, 24];

I would like to use underscore to end up with a result like:

 var allowedPeople = [];
 _.each(_.where(people, { age: _.any()}), function (person) {
            allowedPeople.push(person);
        });

And there may also be occasions where allowedAges is an array of objects and id want to use the contains/any on the people array using a property of the objects in allowedAges.

4 Answers 4

12

The JS equivalent of contains is usually indexOf (and find in rare cases).

You can use the built-in Array.prototype.filter to do this like:

people.filter(function (person) {
  return allowedAges.indexOf(person.age) !== -1; // -1 means not present
});

or with underscore, using the same predicate:

_.filter(people, function (person) {
  return allowedAges.indexOf(person.age) !== -1; // -1 means not present
}

If you have access to ES6 collections or a polyfill for Set, you can replace the allowedAges array with a set (enforcing unique values) and simply use Set.prototype.has:

people.filter(person => allowedAges.has(person.age))
Sign up to request clarification or add additional context in comments.

3 Comments

The OP asked for an underscore solution, not a plain js solution. I can't downvote this because you've answered the question as asked, and the pure js solution can be seen as extra info, but why is the pure js stuff necessary at all given that the OP exlicitly asked a question about underscore? And, why is the 'native' part of your answer first?
@EngineerDollery "I would like to use underscore" Doesn't mean he must use underscore, no where did they state "This must be done using underscore"
@EngineerDollery To promote the built in methods. A lot of people forget about them, but in most browsers now, underscore just defers to them ( underscore is largely a polyfill from before arrays had functional methods). Since the OP asked about underscore, the equivalent solution is there just in case.
3

For the sake of completeness, here's an underscore solution that works with a mixed array of integers and objects containing an age property.

var allowedPeople = _.filter(people, (p) =>
  _.some(allowedAges, (a) => (a.age || a) === p.age)
);

1 Comment

Two different times I've searched and found this post, and both times the first two answers yielded empty arrays for me, but this one from Aldehir has worked both times.
0

Why not use vanilla js filter?

var people = [
  {
    name: 'Dave',
    age: 26
  },
  {
    name: 'Frank',
    age: 23
  }
];

var allowedAges = [20, 23, 24];

var allowedPeople = people.filter(function((person, i, arr) {
  return allowedAges.indexOf(person.age) !== -1;
});

2 Comments

The OP asked for an underscore solution, not a plain js solution.
@EngineerDollery it's very possible OP didn't know there was a non-underscore solution.
0

This is a pure JS version:

var people = [{
  name: 'Dave',
  age: 26
}, {
  name: 'Frank',
  age: 23
}];
var allowedAges = [20, 23, 24];

function filterData(arr, key, searchList){
  var result = [];
  if(Array.isArray(searchList)){
    result = arr.filter(function(item){
      return (searchList.indexOf(item[key])>-1);
    });
  }
  else{
    result = arr.filter(function(item){
      return (searchList === item[key]);
    });
  }
  return result;
}

document.write("<pre>" + JSON.stringify(filterData(people,"age", allowedAges), 0, 4) + "</pre>")

1 Comment

The OP asked for an underscore solution, not a plain js solution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.