按两个不同的键和求和值对数组进行分组
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));
我在 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));