1

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?

5
  • the problem is acc[cur.item] doesn't exist, not that pages doesn't Commented Jun 10, 2024 at 0:00
  • oh, yeah, and pages doesn't exist, not does cur.item.pages Commented Jun 10, 2024 at 0:03
  • But I can aggregate in acc[cur.item]. This is working fine, but only sums the pages for every Item: data.reduce((acc,cur) => { acc[cur.item] = acc[cur.item] + cur.pages || cur.pages return acc },{}) Commented Jun 10, 2024 at 0:11
  • 1
    your code throws an error, so "this is working fine" is a statement that is clearly NOT about this code Commented Jun 10, 2024 at 0:14
  • I mean, what do you think acc[cur.item][pages] is? it's not a property called .pages ... it's a property called 30, 50 or 10 in the case of the data you've presented Commented Jun 10, 2024 at 0:16

2 Answers 2

2
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;
}, []);
Sign up to request clarification or add additional context in comments.

Comments

0

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);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.