简体   繁体   中英

Filter array of objects based on multiple values from another array of objects

I have an array of objects,

c = [
  {
     name: 'abc',
     category: 'cat1',
     profitc: 'profit1',
     costc: 'cost1'
  },
  {
     name: 'xyz',
     category: '',
     profitc: 'profit1',
     costc: ''
  },
  {
     name: 'pqr',
     category: 'cat1',
     profitc: 'profit1',
     costc: ''
  }
]

Now I want to filter array based on another array of objects, the second array of objects is,

arr = [
 {
   type:'profitc'
   value: 'profit1',
 },
 {
   type:'category'
   value: 'cat1',
 }
]

Now the arr is shown in dropdown with multiple select option and the value of key value in the object is shown to the user ie profit1, cat1, etc. So if a user selects profit1 and cat1 , then I need to filter the array c such that, the output looks like this.

c = [
  {
     name: 'abc',
     category: 'cat1',
     profitc: 'profit1',
     costc: 'cost1'
  },
  {
     name: 'pqr',
     category: 'cat1',
     profitc: 'profit1',
     costc: ''
  }
]

I tried doing this.

let result = c.filter(e => {
  let istruecat = true

//arr is chosen value from user.
  arr.forEach(element => {
    istruecat = e[element.type] == element.value;
  })
  return istruecat;
})

But when I do this I get all the objects from the c array. What am I doing wrong here? Is there a an way to do this using lodash.

-You compute istruecat based only on the last entry in arr . You should use reduce instead to accumulate value:

 let result = c.filter(e => arr.reduce((acc, element) => acc && e[element.type] === element.value, true))

You could filter the array by checking all given key/values pairs with the data's objects.

 var data = [{ name: 'abc', category: 'cat1', profitc: 'profit1', costc: 'cost1' }, { name: 'xyz', category: '', profitc: 'profit1', costc: '' }, { name: 'pqr', category: 'cat1', profitc: 'profit1', costc: '' }], filters = [{ type: 'profitc', value: 'profit1', }, { type: 'category', value: 'cat1' }], result = data.filter(o => filters.every(({ type, value }) => o[type] === value)); console.log(result);
 .as-console-wrapper { max-height: 100%;important: top; 0; }

Here's an implementation of reducing the list c based in the given values by the filter array arr . Note that the output is a new list based on the initial content in c .

result = arr.reduce((acc, curr) => {
    acc = acc.filter(item => {
        return item[curr.type] === curr.value;
    });

    return acc;
}, c);

Or a recursive and imo readable solution:

function myFilter(c, [first, ...rest]) {
    if (first) {
        const {type, value} = first;
        // Recursively call myFilter with one filter removed
        return myFilter(c, rest)
           .filter(x => x[type] === value);
    } else {
        // Nothing left to filter
        return c;
    }
}

myFilter(c, arr);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM