0

Assuming that I have 2 multidimensional arrays of objects

const products = [
  {
    id: 1
    name: 'lorem'
  },
  {
    id: 3,
    name: 'ipsum'
  }
];

const tmp_products = [
  {
    id: 1
    name: 'lorem'
  },
  {
    id: 14,
    name: 'porros'
  },
  {
    id: 3,
    name: 'ipsum'
  },
  {
    id: 105,
    name: 'dolor'
  },
  {
    id: 32,
    name: 'simet'
  }
];

What is the correct way to find the missing indexes by id property? I'm expecting an output such as [1,3,4] since those objects are not present in products

I found a similar question but applied to plain arrays: Javascript find index of missing elements of two arrays

var a = ['a', 'b', 'c'],
  b = ['b'],
  result = [];
_.difference(a, b).forEach(function(t) {result.push(a.indexOf(t))});

console.log(result);

I'd like to use ES6 or lodash to get this as short as possible

Luciano
  • 2,052
  • 1
  • 16
  • 26

3 Answers3

2

You can use sets to do it quickly:

const productIds = new Set(products.map(v => v.id));
const inds = tmp_products
    .map((v, i) => [v, i])
    .filter(([v, i]) => !productIds.has(v.id))
    .map(([v, i]) => i);
inds // [1, 3, 4]
Aplet123
  • 33,825
  • 1
  • 29
  • 55
1

You can use Array.prototype.reduce function to get the list of missing products' index.

Inside reduce callback, you can check if the product is included in products array or not using Array.prototype.some and based on that result, you can decide to add the product index or not.

const products = [
  {
    id: 1,
    name: 'lorem'
  },
  {
    id: 3,
    name: 'ipsum'
  }
];

const tmp_products = [
  {
    id: 1,
    name: 'lorem'
  },
  {
    id: 14,
    name: 'porros'
  },
  {
    id: 3,
    name: 'ipsum'
  },
  {
    id: 105,
    name: 'dolor'
  },
  {
    id: 32,
    name: 'simet'
  }
];

const missingIndex = tmp_products.reduce((acc, curV, curI) => {
  if (!products.some((item) => item.id === curV.id && item.name === curV.name)) {
    acc.push(curI);
  }
  return acc;
}, []);

console.log(missingIndex);
Derek Wang
  • 10,098
  • 4
  • 18
  • 39
  • I've changed to this as the accepted answer since other solutions are comparing the whole object. In this way, I can take care only about product ids and compare them based on that. – Luciano Oct 28 '20 at 18:39
1

With lodash you could use differenceWith:

_(tmp_products)
  .differenceWith(products, _.isEqual)
  .map(prod => tmp_products.indexOf(prod))
  .value()

This may not be great for performance, but it depends on how many items you have. With the size of your arrays this should perform ok.

elclanrs
  • 92,861
  • 21
  • 134
  • 171
  • Nice solution. I will handle an array with no more than 10 objects so this fits perfectly. Besides this is the clearest one I'm also able to easily get missing product ids by doing _(tmp_products).differenceWith(products, _.isEqual).map(prod => tmp_products.id).value() – Luciano Oct 28 '20 at 01:41