I found tons of questions related to this issue, but still couldn't figure out what's wrong with my code using .reduce()
array method.
Consider this simple toy data:
const myRecords = [
{ name: "john", preferredColor: "green" },
{ name: "diana", preferredColor: "red" },
{ name: "george", preferredColor: "yellow" },
{ name: "ron", preferredColor: "green" },
{ name: "sarah", preferredColor: "red" },
{ name: "rachel", preferredColor: "red" },
{ name: "nicole", preferredColor: "yellow" },
{ name: "chris", preferredColor: "red" },
];
I want to summarize this data into an object that sums up each color:
{ colorCount: { red: number, yellow: number, green: number } }
To this end, reduce
seems a natural choice. Here's my implementation that doesn't work:
// my attempt
const res = myRecords.reduce(
(acc, person) => // reducer
person.preferredColor === "green"
? (acc.colorCount.green = 1)
: person.preferredColor === "yellow"
? (acc.colorCount.yellow = 1)
: (acc.colorCount.red = 1),
{ colorCount: { red: 0, yellow: 0, green: 0 } } // init value
);
But I get this error
Cannot read properties of undefined (reading 'red')
I can't wrap my head around this. My code seems pretty straightforward. I'm not missing a return
statement because the reducer function is an arrow function without {}
scope. Where's the mistake?
CodePudding user response:
I don't think you can get the result you want using the reduce method but the bellow code works.
const myRecords = [
{ name: "john", preferredColor: "green" },
{ name: "diana", preferredColor: "red" },
{ name: "george", preferredColor: "yellow" },
{ name: "ron", preferredColor: "green" },
{ name: "sarah", preferredColor: "red" },
{ name: "rachel", preferredColor: "red" },
{ name: "nicole", preferredColor: "yellow" },
{ name: "chris", preferredColor: "red" },
];
const result = { colorCount: { red: 0, yellow: 0, green: 0 } };
myRecords.forEach(rec => {
rec.preferredColor === "green"
? (result.colorCount.green = 1)
: rec.preferredColor === "yellow"
? (result.colorCount.yellow = 1)
: (result.colorCount.red = 1);
});
console.log(result);
CodePudding user response:
I saw your code, and you should return the acc
in the reduce. I created another solution version and incremented the corresponding color counter based on the preferredColor
value. You can check it out here:
const myRecords = [
{ name: "john", preferredColor: "green" },
{ name: "diana", preferredColor: "red" },
{ name: "george", preferredColor: "yellow" },
{ name: "ron", preferredColor: "green" },
{ name: "sarah", preferredColor: "red" },
{ name: "rachel", preferredColor: "red" },
{ name: "nicole", preferredColor: "yellow" },
{ name: "chris", preferredColor: "red" },
];
const result = myRecords.reduce((prev, curr) => ({
...prev,
colorCount: {
...prev.colorCount,
[curr.preferredColor]: prev.colorCount[curr.preferredColor] 1
}
}), { colorCount: { red: 0, yellow: 0, green: 0 } })
console.log(result)