29

Is it possible to filter an array of objects by multiple values?

E.g in the sample below can I filter it by the term_ids 5 and 6 and type car at the same time?

[  
   {  
      "id":1,
      "term_id":5,
      "type":"car"
   },
   {  
      "id":2,
      "term_id":3,
      "type":"bike"
   },
   {  
      "id":3,
      "term_id":6,
      "type":"car"
   }
]

Definitely up for using a library if it makes it easier.

5 Answers 5

46

You can do it with Array.filter

var data = [{
    "id": 1,
    "term_id": 5,
    "type": "car"
  },
  {
    "id": 2,
    "term_id": 3,
    "type": "bike"
  },
  {
    "id": 3,
    "term_id": 6,
    "type": "car"
  }
];

var result = data.filter(function(v, i) {
  return ((v["term_id"] == 5 || v["term_id"] == 6) && v.type == "car");
})

console.log(result)

Sign up to request clarification or add additional context in comments.

Comments

16

The following function will help you out.

    nestedFilter = (targetArray, filters) => {
          var filterKeys = Object.keys(filters);
          return targetArray.filter(function (eachObj) {
            return filterKeys.every(function (eachKey) {
              if (!filters[eachKey].length) {
                return true; 
              }
              return filters[eachKey].includes(eachObj[eachKey]);
           });
       });
    };

Use this function with filters described as below:

var filters = {
    "id": ["3"],
    "term_id": ["6"],
    "type": ["car","bike"]
}

Dont pass empty array. If there are no values in the array, skip that property in the filters.

The result will be filtered array.

1 Comment

What if we can check all the input values by lower-casing them to avoid case-sensitive matching? Will that something is like: filters[eachKey.toLowerCase()] and similar for others as well ?
15

You can do this with plain js filter() method and use && to test for both conditions.

var data = [{"id":1,"term_id":5,"type":"car"},{"id":2,"term_id":3,"type":"bike"},{"id":3,"term_id":6,"type":"car"}];

var result = data.filter(function(e) {
  return [5, 6].includes(e.term_id) && e.type == 'car'
});

console.log(result);

2 Comments

Nice! I was trying filter but didn't know it was possible do it like this! Thank you!
@Nenad Vracar, very nice! Is it possible replace searched term without loop through objects? I wanna highlight results.
0

Another way to do it is to use lodash filter + reduce.

const arr = [{"id":1,"term_id":5,"type":"car"},{"id":2,"term_id":3,"type":"bike"},{"id":3,"term_id":6,"type":"car"}];

const result = [
  {term_id: 5, type: 'car'},
  {term_id: 6, type: 'car'},
].reduce((prev, orCondition) => prev.concat(_.filter(arr, orCondition)), []);

console.log(result);
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>

Comments

0

I just had to do this, and it looks like the following would work:

let termFilter = [5,6]
let typeFilter = ['car']
let result = data.filter(({type,term_id}) => termFilter.includes(term_id) && typeFilter.includes(type))

I added the arrays to normalize the code and make it extensible and a bit more readable.

If the conditions are guaranteed never to change, then in one line you could do it like this:

let result = data.filter(({type,term_id}) => [5,6].includes(term_id) && type == 'car')

Comments

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.