Reputation: 539
I want to reduce an array of objects like this:
var data = [{
item: "Item 1",
pages: 30,
chapters: 3
},
{
item: "Item 1",
pages: 50,
chapters: 3
},
{
item: "Item 2",
pages: 10,
chapters: 3
}
]
But aggregating two "fields", so in this case it should end like this:
[
{item: "Item 1", pages: 80, chapters: 6},
{item: "Item 2", pages: 10, chapters: 3}
]
I've tried with a reduce but I can't aggregate more than one field:
data.reduce((acc,cur) => {
acc[cur.item][pages] = acc[cur.item][pages] + cur.item.pages || cur.item.pages
acc[cur.item][chapters] = acc[cur.item][chapters] + cur.item.chapters || cur.item.chapters
return acc
},{})
But this throws errors since it doesn't find the pages
item in the accumulator.
Is it possible to reduce aggregating more than one field of data?
Upvotes: 1
Views: 56
Reputation: 22473
You can achieve this by using reduce
and properly initializing the accumulator:
const data = [
{ item: "Item 1", pages: 30, chapters: 3 },
{ item: "Item 1", pages: 50, chapters: 3 },
{ item: "Item 2", pages: 10, chapters: 3 }
];
let result = data.reduce((acc, cur) => {
if (!acc[cur.item]) {
acc[cur.item] = { item: cur.item, pages: 0, chapters: 0 };
}
acc[cur.item].pages += cur.pages;
acc[cur.item].chapters += cur.chapters;
return acc;
}, {});
result = Object.values(result);
console.log(result);
Upvotes: 0
Reputation: 1733
var data = [{
item: "Item 1",
pages: 30,
chapters: 3
},
{
item: "Item 1",
pages: 50,
chapters: 3
},
{
item: "Item 2",
pages: 10,
chapters: 3
}];
const processedData = data.reduce((items, { item, pages, chapters }) => {
const ensureItemData = () =>
items.find(itemData => itemData.item === item)
?? (() => {
const itemData = { item, pages: 0, chapters: 0 };
items.push(itemData);
return itemData;
})();
const itemData = ensureItemData();
itemData.pages += pages;
itemData.chapters += chapters;
return items;
}, []);
Upvotes: 2