简体   繁体   中英

Common values in array of arrays - lodash

I have an array that looks like this:

const myArray = [
  [
    {id: 1, name: 'Liam'},
    {id: 2, name: 'Oliver'},
    {id: 3, name: 'Jake'},
  ],
  [
    {id: 1, name: 'Liam'},
    {id: 2, name: 'Oliver'},
    {id: 4, name: 'Joe'},
  ],
]

I need to find common elements by id, and return them in an array that would look something like this:

[
  {id: 1, name: 'Liam'},
  {id: 2, name: 'Oliver'},
]

If there isn't any way to do it with lodash, just JS could work too. Note that I do not know how many of these arrays I will have inside, so it should work for any number.

You can use lodash's _.intersectionBy() . You'll need to spread myArray because _intersectionBy() expect arrays as arguments, and not a single array of array:

 const myArray = [[{"id":1,"name":"Liam"},{"id":2,"name":"Oliver"},{"id":3,"name":"Jake"}],[{"id":1,"name":"Liam"},{"id":2,"name":"Oliver"},{"id":4,"name":"Joe"}]] const result = _.intersectionBy(...myArray, 'id') console.log(result)
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js" integrity="sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==" crossorigin="anonymous"></script>

A vanilla solution can be as simple as a filter() call on the first element of the array checking to see that every() subsequent element contains some() elements that match.

 const [srcElement, ...compArray] = [...myArray]; const intersection = srcElement.filter(o => ( compArray.every(arr => arr.some(p => p.id === o.id))) ); console.log(intersection)
 .as-console-wrapper { max-height: 100%;important: top; 0; }
 <script> const myArray = [ [{ id: 1, name: 'Liam' }, { id: 2, name: 'Oliver' }, { id: 3, name: 'Jake' }], [{ id: 1, name: 'Liam' }, { id: 2, name: 'Oliver' }, { id: 4, name: 'Joe' }], [{ id: 1, name: 'Liam' }, { id: 2, name: 'Oliver' }, { id: 5, name: 'Dean' }, { id: 6, name: 'Mara' }] ] </script>

Nowadays vanilla ES is pretty powerful to work with collections in a functional way even without the help of utility libraries. You can use regular Array 's methods to get a pure JS solution. I've created two examples with pure JS. Of course, there could be more approaches as well. And if you already use Lodash in your application, probably it would be better to just use its high-level implementation in form of _.intersectionBy() proposed above to reduce the code complexity.

const myArray = [
  [
    {id: 1, name: 'Liam'},
    {id: 2, name: 'Oliver'},
    {id: 3, name: 'Jake'},
  ],
  [
    {id: 1, name: 'Liam'},
    {id: 2, name: 'Oliver'},
    {id: 4, name: 'Joe'},
  ],
];

// Regular functional filter-reduce
const reducer = (accum, x) => {
  return accum.findIndex(y => x.id == y.id) < 0
    ? [...accum, x]
    : accum;
};

const resultFilterReduce = myArray
  .flat()
  .filter(x => myArray.every(y => y.findIndex(obj => obj.id === x.id) > -1))
  .reduce(reducer, []);

console.log(resultFilterReduce);

// Filter-reduce with using of "HashMap" to remove duplicates
const resultWithHashMap = Object.values(
  myArray
    .flat()
    .filter(x => myArray.every(y => y.findIndex(obj => obj.id === x.id) > -1))
    .reduce((accum, x) => {
      accum[x.id] = x;
      return accum;
    }, {})
  );

console.log(resultWithHashMap);

Use nested forEach loops and Set . Go over each sub-array and find out the common items so far.

 const intersection = ([firstArr, ...restArr]) => { let common = new Set(firstArr.map(({ id }) => id)); restArr.forEach((arr) => { const newCommon = new Set(); arr.forEach(({ id }) => common.has(id) && newCommon.add(id)); common = newCommon; }); return firstArr.filter(({ id }) => common.has(id)); }; const myArray = [ [ { id: 1, name: "Liam" }, { id: 2, name: "Oliver" }, { id: 3, name: "Jake" }, ], [ { id: 1, name: "Liam" }, { id: 2, name: "Oliver" }, { id: 4, name: "Joe" }, ], [ { id: 2, name: "Oliver" }, { id: 4, name: "Joe" }, ], ]; console.log(intersection(myArray));

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