0

If have a JSON object, how can I use.filter to filter my array based on a filters object.

data = [
   {month: 'Sep', name: 'Fred', department: 'Accounting'},
   {month: 'Sep', name: 'David', department: 'Sales'},
   {month: 'Oct', name: 'Jon', department: 'Sales'}
]

filters = {
    month: [],
    name: ['Jon'],
    department: ['Sales','Accounting']
}
3
  • Theres no 2d array here. Its unclear what you want to do Commented Dec 12, 2017 at 18:40
  • Excellent observation Commented Dec 12, 2017 at 18:42
  • I changed the title Commented Dec 12, 2017 at 19:02

4 Answers 4

1

let data = [
 { month: 'Sep', name: 'Fred', department: 'Accounting' },
 { month: 'Sep', name: 'David', department: 'Sales' },
 { month: 'Oct', name: 'Jon', department: 'Sales' }
];

let filters = {
  month: [],
  name: ['Jon'],
  department: ['Sales', 'Accounting']
};

let matches = data.filter(function (o) {
  // iterate through keys of filter object
  for (const key in this) {
    // if filter array is empty and
    // value is not in filter array
    if (this[key].length > 0 && !this[key].includes(o[key])) {
      // object is not match
      return false;
    }
  }
  
  // if object passed every filter array
  // object is match
  return true;
}, filters);

console.log(matches);

A more compact way of writing it could be like this:

let data = [
  { month: 'Sep', name: 'Fred', department: 'Accounting' },
  { month: 'Sep', name: 'David', department: 'Sales' },
  { month: 'Oct', name: 'Jon', department: 'Sales' }
];

let filters = {
  month: [],
  name: ['Jon'],
  department: ['Sales', 'Accounting']
};

let matches = data.filter(function (o) {
  return Object.keys(this).every(
    key => this[key].length === 0 || this[key].includes(o[key])
  );
}, filters);

console.log(matches);

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

2 Comments

I dont see any advantage of key of Object.keys(this) over key in filters
@JonasW. one advantage is that the former does not iterate inherited enumerable keys, only own enumerable, but I do agree in this case it's easier to use for...in.
1
 const result = data.filter(entry => {
   for(var key in filters){
     if(filters[key].length && !filters[key].includes(entry[key]) )
        return false;
   }
   return true;
});

You could filter your data by checking every filter's key to exist in the object and that its value is included in the filtering array.

Comments

1

You can do this with filter() and every() methods.

var data = [
   {month: 'Sep', name: 'Fred', department: 'Accounting'},
   {month: 'Sep', name: 'David', department: 'Sales'},
   {month: 'Oct', name: 'Jon', department: 'Sales'}
]

var filters = {
    month: [],
    name: ['Jon'],
    department: ['Sales','Accounting']
}

var result = data.filter(e => {
  return Object.keys(filters).every(f => {
    return filters[f].includes(e[f]) || !filters[f].length
  })
})


console.log(result)

Comments

0
data.filter(obj => filters.month.indexOf(obj.month) > -1 && filters.name.indexOf(obj.name) > -1 && filters.department.indexOf(obj.department) > -1)

1 Comment

Please explain your code. Without teaching, you're just dumping out an answer, which is a bad answer.

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.