I have an array of objects
const data = [
{ category: 'shopping', amount: 50 },
{ category: 'rent', amount: 1000 },
{ category: 'groceries', amount: 20 },
{ category: 'shopping', amount: 50 }
]
and I am trying to sum up the amounts per category
const result = [
{ category: 'shopping', amount: 100 },
{ category: 'rent', amount: 1000 },
{ category: 'groceries', amount: 20 }
]
So far, I'm thinking of removing the 'duplicates' of categories and store them into an array
const temp = data.map((obj) => {
return obj.category
})
const categories = [...new Set(temp)] // ['shopping','rent','groceries']
With the above, i'm thinking of doing a nested loop but after many tries, I have failed.
Any help is appreciated
You can use reduce() to do that.
Iterate on given data and if an item with same category as current item exists, then add the amount, else add current item as a new entry.
const data = [
{ category: 'shopping', amount: 50 },
{ category: 'rent', amount: 1000 },
{ category: 'groceries', amount: 20 },
{ category: 'shopping', amount: 50 }
];
let result = data.reduce((acc, curr) => {
let item = acc.find(item => item.category === curr.category);
if (item) {
item.amount += curr.amount;
} else {
acc.push(curr);
}
return acc;
}, []);
console.log(result);
Here is an alternative approach using object as the accumulator. This has a performance benefit as we wouldn't have to call find() on every iteration. Credits to frodo2975 for the suggestion.
const data = [
{ category: 'shopping', amount: 50 },
{ category: 'rent', amount: 1000 },
{ category: 'groceries', amount: 20 },
{ category: 'shopping', amount: 50 }
];
let result = Object.values(data.reduce((acc, curr) => {
let item = acc[curr.category];
if (item) {
item.amount += curr.amount;
} else {
acc[curr.category] = curr;
}
return acc;
}, {}));
console.log(result);
I would focus on efficiently computing the totals for each category, and then restructuring the data in the format that you need. So something like this:
// Construct an object mapping category to total amount.
const totals = data.reduce((totals, { category, amount }) => {
totals[category] = (totals[category] || 0) + amount;
}, {});
// Format the data as you like.
const result = Object.entries(totals).map(([category, amount]) => ({ category, amount });
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With