Kasper Juner
Kasper Juner

Reputation: 952

How to reduce array of objects if another array contains objects?

I have two arrays of objects, one contains Shops with it's id, name etc. and another with Products each product has shop_id property in it and i have a filter function which by passing Shop id returns all Products of that shop. The issue is that there could be Shops without items and i would remove that Shops from the array.

So i was going to use .reduce to do it with a .filter on Products Array but i can't get on how i can return the array with only Shops that has some items

i was trying to do something like this

var shops = [ { id: 123, desc: 'Pippo' }, { id: 124, desc: 'Pluto' }, { id: 125, desc: 'Gianni' } ]
const products = [ { id: 1, desc: 'Car', shop: 123 }, { id: 2, desc: 'Jet', shop: 123 }, { id: 3, desc: 'Pizza', shop: 124 } ]

shops = shops.reduce((a,b) => {
  products.filter((item) => item.menu === b.id).length ? b : a
})

console.log(shops) // shouldn't return shop 125 as no items in products for its id.

Upvotes: 1

Views: 456

Answers (2)

3limin4t0r
3limin4t0r

Reputation: 21110

You could group the products based on their shop property, creating a lookup object in the process. This method should be faster when working with large amounts of shops and products, since you only iterate products once.

var shops = [ { id: 123, desc: 'Pippo' }, { id: 124, desc: 'Pluto' }, { id: 125, desc: 'Gianni' } ];
const products = [ { id: 1, desc: 'Car', shop: 123 }, { id: 2, desc: 'Jet', shop: 123 }, { id: 3, desc: 'Pizza', shop: 124 } ];

const productsByShop = groupBy(products, product => product.shop);
shops = shops.filter(shop => productsByShop.get(shop.id));
console.log(shops) // shouldn't return shop 125 as no items in products for its id.

// helper
function groupBy(iterable, fn) {
  const groups = new Map();
  for (const item of iterable) {
    const key = fn(item);
    if (!groups.has(key)) groups.set(key, []);
    groups.get(key).push(item);
  }
  return groups;
}

Upvotes: 0

ray
ray

Reputation: 27245

I think you could accomplish this with array.filter and array.some:

const shops = [{ id: 'shop1' },{ id: 'shop2' },{ id: 'shop3'},]
const products = [
  { pid: 'product1', shop: 'shop1'},
  { pid: 'product3', shop: 'shop3'},  
];

const shopsWithProducts = shops.filter(shop => products.some(p => p.shop === shop.id));

console.log(shopsWithProducts);

Upvotes: 2

Related Questions