4

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 }
]
Kay Singian
  • 1,301
  • 8
  • 20
  • 33
  • 3
    Have you tried anything thus far? Can you provide the sample data and expected output? – nem035 Mar 26 '18 at 06:11
  • 1
    @nem035 I added examples and expected output. I'm stuck between having to choose if I should use filter, map, reduce, or Object.assign. – Kay Singian Mar 26 '18 at 06:21

4 Answers4

5

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)
Yury Tarabanko
  • 44,270
  • 9
  • 84
  • 98
4

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:

Mohammad Usman
  • 37,952
  • 20
  • 92
  • 95
0
data
    .sort((a, b) => a.material_no - b.material_no)
    .map(({material_no, material_name, qty}, index, arr) => ({
        material_no,
        material_name,
        qty: qty + (material_no === (arr[index - 1] || {}).material_no && arr[index - 1].qty)
    }))
    .filter(({material_no}, index, arr) => material_no !== (arr[index + 1] || {}).material_no);

It's slow and just for fun :)

troy
  • 387
  • 1
  • 9
0
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 accumulation = data.reduce((total, val, index)=>{
  let foundItemIndex = total.findIndex((obj)=>obj.material_no == val.material_no);
  if(foundItemIndex < 0) total.push(val) 
  else total[foundItemIndex].qty += val.qty;
  return total;
}, []);

console.log(accumulation);
Sarim Javaid Khan
  • 810
  • 15
  • 30