Reputation: 146
I'm working with an array on React and i'm trying to filter it by month and year, i managed to do it by month but for some reason i can't add the year key, this is what i have so far:
This is the array that i have originally:
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"
This is the groupBy function:
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;
}
And this is the result i have:
grouped = [
{name:11, values: [155,120...]},
{name:12, values: [135...]
];
And what i want to to is to also have it grouped by the year, so for example, the month 11, shouldn't have two values, because on the original array i have on month that's 11 from 2020 and one from 2021, so what i want to have as a result is this:
grouped = [
{name:11/2020, values: [155...]},
{name:11/2021, values: [120...]},
{name:12/2020, values: [135...]
];
Can anyone help me with this?
Upvotes: 0
Views: 1468
Reputation: 912
Working with Array.reduce
method could be more simple, for the example I added some values:
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))
EDIT -----------------
I edited the code to use the group by function and to produce an array containing the values and the sum. you can group passing an array containing first level key (like ['month']
or ['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(
data.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));
Upvotes: 1
Reputation: 327
If I understand correctly you want to sum all values per month per year. I guess this will work.
// 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));
Upvotes: 1