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 });
Just another version of using reduce
method:)
const data = [ { category: 'shopping', amount: 50 }, { category: 'rent', amount: 1000 }, { category: 'groceries', amount: 20 }, { category: 'shopping', amount: 50 } ]; const result = data.reduce((a,c) => { a[c.category] = a[c.category] || {category: c.category, amount: 0}; a[c.category].amount += c.amount; return a; }, {}) console.log(Object.values(result));
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.