'JavaScript Reduce with Objects

This is my object

   let products = [
      { "productName": "A", "storage": "Lot 1", "quantity": 1000, "status": "stockIn" },
      { "productName": "A", "storage": "Lot 1", "quantity": 100, "status": "stockIn"  },
      { "productName": "A", "storage": "Lot 1", "quantity": 500, "status": "stockOut" },
      { "productName": "A", "storage": "Lot 2", "quantity": 500, "status": "stockIn"  }
   ]

This is what I am trying to achieve

   let result = [
      { "productName": "A", "storage": "Lot 1", "stockIn": 1100, "stockOut": 500, "available":600 },
      { "productName": "A", "storage": "Lot 2", "stockIn": 500, "stockOut": 0, "available":500   }
   ]

Please kindly provide an idea on how to achieve this without redundant codes. Thanks

var storage = new Set(products.map(item => item.storage));

storage.forEach(lot => {

var stockIn = products.filter(item => item.storage === storage && item.status == 'stockIn')
    .map(({ storage, quantity }) => ({ storage, quantity }));

var stockInSum = stockIn.reduce((prev, curr, index) => prev + curr.quantity, 0);

var stockOut = products.filter(item => item.storage === storage && item.status == 'stockOut')
    .map(({ storage, quantity }) => ({ storage, quantity }))

var stockOutSum = stockOut.reduce((prev, curr, index) => prev + curr.quantity, 0);

}


Solution 1:[1]

Here is the general pattern. I will leave it to you to figure out the other fields.

const reduced = products.reduce( (a,v) => {
  const found = a.find(it=>it.lot === v.lot && it.productName === v.productName)
  if (found) {
    a.quantity += v.quantity
    // aggregate your other fields here.
  }
  else {
    a.push(v)
  }
  return a
}, [] )

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Steven Spungin