I have an array of objects. I want to reduce this array of objects based on the property category
, so that I can get a total sum of each category. I wrote this function which returns an object:
const expenses =
[{
title: 'burger',
sum: 57,
category: 'eating_out',
notes: 'was good',
},
{
title: 'water bill',
sum: 142.81,
category: 'utilities',
notes: 'this sucks',
},
{
title: 'electricity bill',
sum: 112.90,
category: 'utilities',
notes: 'could be worse',
}]
const totalExpensesByCategory = expenses.reduce(
(acc, curr) => {
if (!acc[curr.category]) {
acc[curr.category] = curr.sum;
} else {
acc[curr.category] = acc[curr.category] curr.sum;
}
return acc;
},
{}
);
console.log(totalExpensesByCategory)
I want it to be an iterable object so that I can easily render components based on those entries.
How can I write it differently so that maybe it will return an array of objects that I can use map() on? Object.entries() doesn't seem like the ideal way to do it.
CodePudding user response:
There's no reason not to build it up as an array of objects inside the reduce in the first place:
const totalExpensesByCategory = expenses.reduce(
(acc, curr) => {
const categoryIndex = acc.findIndex((category) => category.name === curr.category)
if (categoryIndex === -1) {
acc.push({name: curr.category, sum: curr.sum})
} else {
acc[categoryIndex].sum = acc[categoryIndex].sum curr.sum;
}
return acc;
},
[]
);
Heres the output:
CodePudding user response:
Since you have valuable info in the object keys (the category) and similar in the values (the sum) you'll need both the key and the value from each object entry to create an array element. One approach is Object.entries, followed by map to create the individual objects that go into the output array.
const expenses =
[{
title: 'burger',
sum: 57,
category: 'eating_out',
notes: 'was good',
},
{
title: 'water bill',
sum: 142.81,
category: 'utilities',
notes: 'this sucks',
},
{
title: 'electricity bill',
sum: 112.90,
category: 'utilities',
notes: 'could be worse',
}]
const totalExpensesByCategory = Object.entries(expenses.reduce(
(acc, curr) => {
if (!acc[curr.category]) {
acc[curr.category] = curr.sum;
} else {
acc[curr.category] = acc[curr.category] curr.sum;
}
return acc;
},
{}
)).map(([k, v]) => ({category: k, sum: v}));
console.log(totalExpensesByCategory);