按两个不同的键和求和值对数组进行分组

Group array by two different keys and sum values

我在 React 上使用一个数组,我试图按月和年过滤它,我设法按月完成,但由于某种原因我无法添加年键,这就是我到目前为止:

这是我原来的数组:

paid = [
 {amount:155, month:11, year:2020, date:11-11-2020}
 {amount:120, month:11, year:2021, date:05-11-2021}
 {amount:135, month:12, year:2020, date:11-12-2020}
...
]

const group = groupBy(d, (invoices) => invoices.month); //d is the array called "paid"

这是 groupBy 函数:

function groupBy(list, keyGetter) {
    const map = new Map();
    list.forEach((item) => {
      const key = keyGetter(item);
      const collection = map.get(key);
      if (!collection) {
        map.set(key, [parseInt(item.amount)]);
      } else {
        collection.push(parseInt(item.amount));
      }
    });
    return map;
  }

这是我得到的结果:

grouped = [
 {name:11, values: [155,120...]},
 {name:12, values: [135...]
];

我想要的是也将它按年份分组,例如,11 月不应该有两个值,因为在原始数组中我有从 2020 年开始的 11 月和一个来自 2021 年,所以我想要的结果是:

grouped = [
 {name:11/2020, values: [155...]},
 {name:11/2021, values: [120...]},
 {name:12/2020, values: [135...]
];

谁能帮我解决这个问题?

如果我没理解错的话,您想对每年每个月的所有值求和。我想这会起作用。

// Generate random data.
const genData = () => {
  const d = [];
  for(let i =0; i < 1000; i++) {
    d.push({
      year: Math.round(Math.random() * 10) + 2001,
      month: Math.round(Math.random() * 12),
      amount: Math.round(Math.random() * 100) + 100
    })
  }
  return d;
};

// Sum all data per month per year
const sumData = (d) => {
  const summed = {};
  for(const {year,month,amount} of d) {
    // By using a unique key for each year/month combi you can easily access the
    // intermedeiate result and add another value.
    const key = year + '/' + month;
    
    // If it does not yet exist, create an empty record for this year/month
    if(!(key in summed)) {
      summed[key] = {year,month, sum:0, values:[]};
    }
    
    // Grab the intermediate values and add amount to sum and to values
    summed[key].values.push(amount)
    summed[key].sum += amount;
  }
  return Object.values(summed);
};

// Run all
const d = genData();
console.log(d);
console.log(sumData(d));

使用 Array.reduce 方法可能更简单,例如我添加了一些值:

const paid = [
 {amount:155, month:11, year:2020, date:'11-11-2020'},
 {amount:160, month:11, year:2020, date:'11-11-2020'},
 {amount:120, month:11, year:2021, date:'05-11-2021'},
 {amount:130, month:11, year:2021, date:'05-11-2021'},
 {amount:135, month:12, year:2020, date:'11-12-2020'},
 {amount:145, month:12, year:2020, date:'11-12-2020'}
]
const grouped = paid.reduce((acc,val)=>{
    if(acc[val.month+'/'+val.year]){
        acc[val.month+'/'+val.year].push(val.amount)
    } else {
        acc[val.month+'/'+val.year] = [val.amount]
    }
    return acc
}, {})
console.log(JSON.stringify(grouped,null,2))

编辑 ------------------
我编辑了代码以使用 group by 函数并生成一个包含值和总和的数组。您可以分组传递包含一级键的数组(如 ['month']['month', 'year']):

const paid = [
  { amount: 155, month: 11, year: 2020, date: "11-11-2020" },
  { amount: 160, month: 11, year: 2020, date: "11-11-2020" },
  { amount: 120, month: 11, year: 2021, date: "05-11-2021" },
  { amount: 130, month: 11, year: 2021, date: "05-11-2021" },
  { amount: 135, month: 12, year: 2020, date: "11-12-2020" },
  { amount: 145, month: 12, year: 2020, date: "11-12-2020" }
];

const groupBy = (data, keys) => {
  return Object.values(
    paid.reduce((acc, val) => {
      const name = keys.reduce((finalName,key)=> finalName + val[key]+'/','').slice(0, -1)
      if (acc[name]) {
        acc[name].values.push(val.amount);
        acc[name].sum += val.amount;
      } else {
        acc[name] = {
          name,
          sum:val.amount,
          values:[val.amount]
        };;
      }
      return acc;
    }, {})
  );
};

console.log(JSON.stringify(groupBy(paid, ['month','year']), null, 2));