Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 626
marielle Avatar asked Dec 04 '25 04:12

marielle


2 Answers

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)
like image 109
Sebastian Kaczmarek Avatar answered Dec 06 '25 17:12

Sebastian Kaczmarek


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);
like image 44
Nina Scholz Avatar answered Dec 06 '25 18:12

Nina Scholz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!