1

Given I have this array of objects:

    let array1 = [
        {id: 1, name: "Test Item 1", price: 100, type: 'item'},
        {id: 1, name: "Test Fee 1", price: 200, type: 'fee'},
        {id: 3, name: "Test 3", price: 300, type: 'item'},
    ]

Now i want to filter so I only have the objects where every key value of the following array match:

    let array2 = [
        {id: 1, type: "item"},
        {id: 3, type: "item"},
    ]

This should return array1[0] and array1[2]. My current solution has been this, but it wont work if array2 has multiple object keys to compare to:

array1.filter(row => {
    return array2.find(r => {
        return Object.entries(row).some(([key, value]) => r[key] === value);
    })
});
xTheWolf
  • 1,756
  • 4
  • 18
  • 43
  • Does this answer your question? [Comparing two arrays of objects, and exclude the elements who match values into new array in JS](https://stackoverflow.com/questions/32965688/comparing-two-arrays-of-objects-and-exclude-the-elements-who-match-values-into) – stijnb1234 Oct 21 '22 at 14:39
  • Not really, as that does the inverse and it also filters by a hardcoded key (id), i need to filter by comparing to multiple key/value pairs. – xTheWolf Oct 21 '22 at 14:40
  • @GrafiCode array1 should only return objects where each key/value of one of the objects in array2 match. So not only type is taken into consideration, but also id. (note theres two times the same id on array1 with a different type). I'm just bad at explaining :) – xTheWolf Oct 21 '22 at 14:46
  • Do it the other way round: `Object.entries(r).every(([key, value]) => row[key] === value)`. Get the entries of `r` and check if `every` value in second array is present in the `row` object – adiga Oct 21 '22 at 14:47
  • @adiga You're a hero. Such a simple solution after all. Works flawlessly, thanks! If you post it as an answer, I'll be glad to mark it as the accepted one. – xTheWolf Oct 21 '22 at 14:52

3 Answers3

2
array1.filter((row) =>
  array2.some((template) =>
    Object.keys(template).every((key) => template[key] === row[key])
  )
);

I think the answer in comment above is cleaner than mine.

bbbbbbbboat
  • 443
  • 3
  • 11
1

In array1.filter() you can iterate all objects in array2 and compare keys using Object.keys()

let array1 = [
  {id: 1, name: "Test Item 1", price: 100, type: 'item'},
  {id: 1, name: "Test Fee 1", price: 200, type: 'fee'},
  {id: 3, name: "Test 3", price: 300, type: 'item'},
]

 let array2 = [
   {id: 1, type: "item"},
   {id: 3, type: "item"},
 ]

const res = array1.filter(row => {
  for (const obj of array2) {
    if (Object.keys(obj).every(k => obj[k] === row[k])) {
      return row
    }
  }
})

console.log(res)
GrafiCode
  • 3,307
  • 3
  • 26
  • 31
1

Lodash if you don't mind:

const array1 = [{id: 1, name: "Test Item 1", price: 100, type: 'item'},{id: 1, name: "Test Fee 1", price: 200, type: 'fee'},{id: 3, name: "Test 3", price: 300, type: 'item'}];
const array2 = [{id: 1, type: "item"},{id: 3, type: "item"}];

const fn = _.overSome(array2.map(_.matches));
const result = _.filter(array1, fn);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0 }
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
A1exandr Belan
  • 4,442
  • 3
  • 26
  • 48