ES6 Implementation of Group By and SUM

二次信任 提交于 2021-02-04 07:41:25

问题


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 }
]

回答1:


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)



回答2:


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()



回答3:


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 :)




回答4:


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);


来源:https://stackoverflow.com/questions/49484910/es6-implementation-of-group-by-and-sum

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!