1

I have the following array of objects:

const dataSet = [
  {
    createdOn: '2020-06-01',
    id: 1,
    value: 12
  },
  {
    createdOn: '2020-06-01',
    id: 2,
    value: 23
  },
  {
    createdOn: '2020-06-02',
    id: 3,
    value: 40
  },
  {
    createdOn: '2020-06-03',
    id: 4,
    value: 15
  }
]

What I'd like to be able to return is the follow:

[
  {
    createdOn: '2020-06-01',
    value: 35 // sum of 12 + 23
  },
  {
    createdOn: '2020-06-02',
    value: 75 // sum of 35 + 40
  },
  {
    createdOn: '2020-06-03',
    value: 90 // sum of 75 + 15
  }
]

So the outcome I'm after is:

  1. When there are two (or more) objects with the same createdOn date, then their values should be added together in a single object for that createdOn key.
  2. Each object's value also then needs to be added together, creating an accumulated value from the previous object.

After a bit of searching through SO I found some code which helps me achieve the first point:

dataSet.reduce((acc, cur) => {
  const date = cur.createdOn
  const found = acc.find(elem => elem.createdOn === date)

  if (found) {
    found.value += cur.value
  } else {
    acc.push(cur)
  }
  return acc
}, [])

I just can't figure out how to achieve the accumulated value part.

Thanks in advance, and have a great weekend.

Neil Merton
  • 553
  • 4
  • 17
  • Take a sum variable and loop again on the resulting array. Update the cumulative sum to each object – adiga Jun 12 '20 at 19:29

2 Answers2

1

I would do this like this. First compute cumulative value for each distinct createdOn value and then transform resulting map back to array:

const map = dataSet.reduce((acc, {createdOn, value}) => {
  acc[createdOn] = value + (acc[createdOn] || 0);
  return acc;
}, {});
const result = Object.entries(map).map(([key, value], index) => ({
  createdOn: key,
  value: value
}));
result.forEach((item, index) => {
  if (index) {
     item.value += result[index - 1].value;
  }
});
Alex
  • 1,724
  • 13
  • 25
  • Hey @Aleksey, tried your answer and it returned `[{ createdOn: '2020-06-01', value: 35 },{ createdOn: '2020-06-02', value: 40 },{ createdOn: '2020-06-03', value: 15 }]` so is missing the accumulation of `value` from one object to the next. – Neil Merton Jun 12 '20 at 19:41
  • Sorry I missed that requirement. I edited answer and added one more operation to accumulate values. This code assumes that initial dataSet array was ordered by createdOn date. – Alex Jun 12 '20 at 19:48
1

How about this one:

var dataSet = [ { createdOn: '2020-06-01', id: 1, value: 12 }, { createdOn: '2020-06-01', id: 2, value: 23 }, { createdOn: '2020-06-02', id: 3, value: 40 }, { createdOn: '2020-06-03', id: 4, value: 15 }];

var finalResult = Object.values(dataSet.reduce((acc, {createdOn, value})=>{
    acc[createdOn] = acc[createdOn] || {createdOn, value:0};
    acc[createdOn].value+=value;
    return acc;
},{})).map((e,i,self)=>(e.value+=self[i-1] ? self[i-1].value : 0, e));

console.log(finalResult);
gorak
  • 5,233
  • 1
  • 7
  • 19