2

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?

2
  • The seed data[0] is incorrect. It should be [] because you want it to result into a new array. Additionally, build up this array, you need to return [...r, newDatum], not newDatum Commented Jul 14, 2020 at 14:51
  • reduce function return a single value. in this case, you need to use map function. Commented Jul 14, 2020 at 14:55

3 Answers 3

6

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)

Sign up to request clarification or add additional context in comments.

Comments

5

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

Comments

0
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.

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.