Search code examples
javascriptarraysobjectgrouping

How to group by multiple values and sum an array of objects?


I would like to group an array of objects by type thick width height and sum the amount in jQuery. How can I achieve this?

For example:

var array = [
  { type: "alu", thick : 1 ,width:1000, height:2000 , amount: 50 },
  { type: "alu", thick : 1 ,width:1000, height:2000, amount: 30 },
  { type: "alu", thick : 1.5 ,width:1000, height:2000, amount: 20 },
  { type: "metal", thick : 2 ,width:1500, height:3000, amount: 15 }
]

Should result in:

var array = [
  { type: "alu", thick : 1 ,width:1000, height:2000 , amount: 80 },
  { type: "alu", thick : 1.5 ,width:1000, height:2000, amount: 20 },
  { type: "metal", thick : 2 ,width:1500, height:3000, amount: 15 }
]

since all the type , thick , width and height match the should merge but still add the amounts


Solution

  • You can do something like the below, using vanilla JS:

    var array = [
      { type: "alu", thick: 1, width: 1000, height: 2000, amount: 50 },
      { type: "alu", thick: 1, width: 1000, height: 2000, amount: 30 },
      { type: "alu", thick: 1.5, width: 1000, height: 2000, amount: 20 },
      { type: "metal", thick: 2, width: 1500, height: 3000, amount: 15 }
    ];
    
    const res = [];
    
    const process = () =>
      array.forEach((r) => {
        const found = res.find(
          (a) =>
            a.type == r.type &&
            a.thick == r.thick &&
            a.width == r.width &&
            a.height == r.height
        );
        if (found) {
          found.amount += r.amount;
        } else {
          res.push({ ...r });
        }
      });
    
    process();
    console.log(res);
    

    Which returns:

    [
        {
            "type": "alu",
            "thick": 1,
            "width": 1000,
            "height": 2000,
            "amount": 80
        },
        {
            "type": "alu",
            "thick": 1.5,
            "width": 1000,
            "height": 2000,
            "amount": 20
        },
        {
            "type": "metal",
            "thick": 2,
            "width": 1500,
            "height": 3000,
            "amount": 15
        }
    ]
    

    Alternatively you can use reduce:

    const res = array.reduce((acc, el) => {
      const found = acc.find(
        (a) =>
          a.type == el.type &&
          a.thick == el.thick &&
          a.width == el.width &&
          a.height == el.height
      );
      if (found) {
        found.amount += el.amount;
      } else {
        acc.push({ ...el });
      }
      return acc;
    }, []);
    
    console.log(res);