-2

I have a Json array with data like this

0: Product {Name: "--Product Name--", CategoryID: "115", Sku: "xxxx", Quantity: 1, Price: 4}
1: Product {Name: "--Product Name--", CategoryID: "115", Sku: "xxxx", Quantity: 1, Price: 4}
2: Product {Name: "--Product Name--", CategoryID: "115", Sku: "xxxx", Quantity: 1, Price: 4}
3: Product {Name: "--Product Name--", CategoryID: "77", Sku: "xxxx", Quantity: 1, Price: 9.99}
4: Product {Name: "--Product Name--", CategoryID: "77", Sku: "xxxx", Quantity: 2, Price: 9.99}
5: Product {Name: "--Product Name--", CategoryID: "77", Sku: "xxxx", Quantity: 1, Price: 9.99}
6: Product {Name: "--Product Name--", CategoryID: "77", Sku: "xxxx", Quantity: 4, Price: 9.99}

I want to create a brief summary of the products stored in the object, by their category Id and their quantity and cost

So the output would be something similar to:

 Category Id    Quantity    Cost
     115           3        12
     77            8        79.92

Is there an easy way of doing this without making a number of arrays to show which category IDs are in the object and cycling through each product array and then category array in a nested for loop?

vmp
  • 271
  • 1
  • 3
  • 13
  • 1
    Possible duplicate of [Most efficient method to groupby on a array of objects](https://stackoverflow.com/questions/14446511/most-efficient-method-to-groupby-on-a-array-of-objects) – George Jan 03 '19 at 14:08
  • This isn't valid JSON. Have you tried something? – barbsan Jan 03 '19 at 14:11

2 Answers2

3

You can use array#reduce to group the array on CategoryID in an object accumulator.

let products = [{Name: "--Product Name--", CategoryID: "115", Sku: "xxxx", Quantity: 1, Price: 4},{Name: "--Product Name--", CategoryID: "115", Sku: "xxxx", Quantity: 1, Price: 4}, {Name: "--Product Name--", CategoryID: "115", Sku: "xxxx", Quantity: 1, Price: 4},{Name: "--Product Name--", CategoryID: "77", Sku: "xxxx", Quantity: 1, Price: 9.99}, {Name: "--Product Name--", CategoryID: "77", Sku: "xxxx", Quantity: 2, Price: 9.99}, {Name: "--Product Name--", CategoryID: "77", Sku: "xxxx", Quantity: 1, Price: 9.99},{Name: "--Product Name--", CategoryID: "77", Sku: "xxxx", Quantity: 4, Price: 9.99}],
    result = Object.values(products.reduce((r, o) => {
      r[o.CategoryID] = r[o.CategoryID] || {CategoryID: o.CategoryID, Quantity: 0, Price: 0};
      r[o.CategoryID]['Quantity'] += o.Quantity;
      r[o.CategoryID]['Price'] += o.Price;
      return r;
    }, {}));
console.log(result);
Hassan Imam
  • 21,956
  • 5
  • 41
  • 51
0

You can use Array.reduce for a compact code, but you can also use Array.forEach for added clarity:

// creates dummy data
let data = (new Array(100)).fill().map(() => ({
  id: Math.floor(3 * Math.random()),
  quantity: Math.random(),
  cost: Math.random()
}));

// summary object
let summary = {};

// add keys
data.forEach(d => {
  if (summary[d.id] == undefined) {
    summary[d.id] = {
      quantity: 0,
      cost: 0
    };
  }
});

// populate summary
data.forEach(d => {
  summary[d.id].quantity += d.quantity;
  summary[d.id].cost += d.cost;
});

console.log(summary);
Nino Filiu
  • 16,660
  • 11
  • 54
  • 84