Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ES6 Implementation of Group By and SUM [duplicate]

I have an array of objects with these properties: material_no, material_name, qty.

let data = [
  { material_no: '1001', material_name: 'Material 1', qty: 100 },
  { material_no: '1001', material_name: 'Material 1', qty: 50 },
  { material_no: '1002', material_name: 'Material 2', qty: 44 },
  { material_no: '1003', material_name: 'Material 3', qty: 125 },
  { material_no: '1002', material_name: 'Material 2', qty: 59 },
  { material_no: '1004', material_name: 'Material 4', qty: 999 },
  { material_no: '1005', material_name: 'Material 5', qty: 80 },
  { material_no: '1005', material_name: 'Material 5', qty: 66 }
]

How do I return an array of objects grouped by their material_no/material_name and sum of the qty having the same material_no/material_name?

[
  { material_no: '1001', material_name: 'Material 1', qty: 150 },
  { material_no: '1002', material_name: 'Material 2', qty: 103 },
  { material_no: '1003', material_name: 'Material 3', qty: 125 },
  { material_no: '1004', material_name: 'Material 4', qty: 999 },
  { material_no: '1005', material_name: 'Material 5', qty: 146 }
]
like image 843
Kay Singian Avatar asked Sep 03 '25 09:09

Kay Singian


2 Answers

You could reduce array to a Map that stores total items by material_no. And then just extract map values to array.

let data = [
  { material_no: '1001', material_name: 'Material 1', qty: 100 },
  { material_no: '1001', material_name: 'Material 1', qty: 50 },
  { material_no: '1002', material_name: 'Material 2', qty: 44 },
  { material_no: '1003', material_name: 'Material 3', qty: 125 },
  { material_no: '1002', material_name: 'Material 2', qty: 59 },
  { material_no: '1004', material_name: 'Material 4', qty: 999 },
  { material_no: '1005', material_name: 'Material 5', qty: 80 },
  { material_no: '1005', material_name: 'Material 5', qty: 66 }
]

const sums = [
  ...data.reduce(
    (map, item) => {
      const { material_no: key, qty } = item;
      const prev = map.get(key);
      
      if(prev) {
        prev.qty += qty
      } else {
        map.set(key, Object.assign({}, item))
      }
      
      return map
    },
    new Map()
  ).values()
]

console.log(sums)
like image 70
Yury Tarabanko Avatar answered Sep 04 '25 23:09

Yury Tarabanko


You can use .reduce() like this:

let data = [{ material_no: '1001', material_name: 'Material 1', qty: 100 },{ material_no: '1001', material_name: 'Material 1', qty: 50 },{ material_no: '1002', material_name: 'Material 2', qty: 44 },{ material_no: '1003', material_name: 'Material 3', qty: 125 },{ material_no: '1002', material_name: 'Material 2', qty: 59 },{ material_no: '1004', material_name: 'Material 4', qty: 999 },{ material_no: '1005', material_name: 'Material 5', qty: 80 },{ material_no: '1005', material_name: 'Material 5', qty: 66 }];

let result = Object.values(
               data.reduce((a, c) => (
                 a[c.material_no] = a[c.material_no] ?
                 (a[c.material_no].qty += c.qty, a[c.material_no]) :
                 c, a), {}
               )
             );

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Useful Resources:

  • Array.prototype.reduce()
  • Arrow Functions
  • Object.values()
like image 36
Mohammad Usman Avatar answered Sep 04 '25 21:09

Mohammad Usman