Home > other >  Using reduce array method to sum up (increment) records properties results with an undefined error
Using reduce array method to sum up (increment) records properties results with an undefined error

Time:08-07

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)

  • Related