Skip to content
Advertisement

How to compare a nested array of objects and only return common values

I have a nested array of objects which contains some duplicate values:

[
  [
    {
      name: 'name1',
      email: 'email1'
    },
    {
      name: 'name2',
      email: 'email2'
    }
  ],
  [
    {
      name: 'name1',
      email: 'email1'
    }
  ],
  [
    {
      name: 'name1',
      email: 'email1'
    },
    {
      name: 'name2',
      email: 'email2'
    }
  ]
]

I want to create a new single array from this data containing only the objects that exist in all the nested arrays:

[
  {
    name: 'name1',
    email: 'email1'
  }
]

I have tried the following code:

const filteredArray = arrays.shift().filter(function (v) {
  return arrays.every(function (a) {
    return a.indexOf(v) !== -1;
  });
});
console.log('filteredArray => ', filteredArray);

and:

const filteredArray = arrays.reduce((p,c) => p.filter(e => c.includes(e)));
console.log('filteredArray => ', filteredArray);

However these both only return an empty array.

Would really appreciate any help. TIA

Advertisement

Answer

You could create a Map with objects from the first subarray, keyed by their JSON representation (after ordering their keys). Then filter the next subarray for objects whose JSON representation is in that map, and put those in a new map. Continue like that for all subarrays. Finally return the values that remain in the last map:

// Helper functions:
const str = o => JSON.stringify(Object.keys(o).sort().map(key => [key, o[key]]));
const mapify = arr => new Map(arr.map(o => [str(o), o]));

const intersection = data => !data.length ? [] :
    [...data.slice(1).reduce((map, arr) =>
        mapify(arr.filter(o => map.get(str(o)))),
    mapify(data[0])).values()];

const data = [[{name: 'name1',email: 'email1'},{name: 'name2',email: 'email2'}],[{name: 'name1',email: 'email1'}],[{name: 'name1',email: 'email1'},{name: 'name2',email: 'email2'}]]

console.log(intersection(data));
Advertisement