Use reduce to sum values in array of objects

I have this array of objects:

const data = [   {val: 40, color: 'red'},   {val: 5, color: 'green'},   {val: 55, color: 'lime'} ] 

This is what I would like to obtain:

const result = [   {val: 40, color: 'red'},   {val: 45, color: 'green'},   {val: 100, color: 'lime'} ] 

So each item should have the same color and the cumulative value of previous data.

This is what I try:

const data = [   {val: 40, color: 'red'},   {val: 5, color: 'green'},   {val: 55, color: 'lime'} ]  // const result = [ //   {val: 40, color: 'red'}, //   {val: 45, color: 'green'}, //   {val: 100, color: 'lime'} // ]  const result = data.reduce((r, value, i) => {     const { val, color } = value     const cumVal = i === 0 ? val : r[i - 1].val     const newDatum = { val: cumVal, color }     return newDatum }, data[0])  console.log(result)

Where is the error? Why r[i - 1] is undefined?

Add Comment
3 Answer(s)

You had four issues in your code:

  • In this line const cumVal = i === 0 ? val : r[i - 1].val you should assign 0 as a default value, not val
  • In this line const newDatum = { val: cumVal, color } you need to add val to cumVal
  • As an initial value, you should pass an empty array, not the first element of your data array, because you want to have an array as a result, not an object
  • You need to return the r in every iteration, not newDatum – again, you want to have an array in the end, not an object

Here is a fixed version:

const data = [   {val: 40, color: 'red'},   {val: 5, color: 'green'},   {val: 55, color: 'lime'} ]  // const result = [ //   {val: 40, color: 'red'}, //   {val: 45, color: 'green'}, //   {val: 100, color: 'lime'} // ]  const result = data.reduce((r, value, i) => {     const { val, color } = value     const cumVal = i === 0 ? 0 : r[i - 1].val     const newDatum = { val: val + cumVal, color }     r.push(newDatum);     return r; }, [])  console.log(result)

Answered on July 16, 2020.
Add Comment

You start the reduce with a single element, which is not an array.

Instead, you could take a closure over sum and map new objects.

const     data = [{ val: 40, color: 'red' }, { val: 5, color: 'green' }, { val: 55, color: 'lime' }],     result = data.map(         (sum => ({ val, color }) => ({ val: sum += val, color }))         (0)     );  console.log(result);

Answered on July 16, 2020.
Add Comment
const result2 = data.reduce((acc, { val, color }, i) => {     val += (i>0) ? acc[i - 1].val: 0;     return acc.concat([{ val, color }]) }, []) 

the solution to your problem.

issues:

  1. wrong initial value
  2. returning object

though I think Map would be a better choice here.

Answered on July 16, 2020.
Add Comment

Your Answer

By posting your answer, you agree to the privacy policy and terms of service.