0

I have an array with values per date but would like to sum up all values on hour instead of separate date/hour. I guess I could iterate over it and remove yyyy-mm-dd and then sum up on duplicate hour object but is there a smarter way?

  {
    "series": [
      {
        "value": 1,
        "category": "2021-03-04T04:00:00.000"
      },
      {
        "value": 2,
        "category": "2021-03-04T05:00:00.000"
      },
      {
        "value": 3,
        "category": "2021-03-04T06:00:00.000"
      },
      {
        "value": 1,
        "category": "2021-03-05T04:00:00.000"
      },
      {
        "value": 2,
        "category": "2021-03-05T05:00:00.000"
      },
      {
        "value": 3,
        "category": "2021-03-05T06:00:00.000"
      }
    ]
  }
]

So the array below should only be:

[
  {
    "series": [
      {
        "value": 2,
        "category": "04:00:00.000"
      },
      {
        "value": 4,
        "category": "05:00:00.000"
      },
      {
        "value": 6,
        "category": "06:00:00.000"
      }
    ]
  }
]
codehippy
  • 21
  • 3
  • Welcome to Stack Overflow! Visit the [help], take the [tour] to see what and [ask]. Please first ***>>>[Search for related topics on SO](https://www.google.com/search?q=javascript+sum+object+array+site%3Astackoverflow.com)<<<*** and if you get stuck, post a [mcve] of your attempt, noting input and expected output using the [`[<>]`](https://meta.stackoverflow.com/questions/358992/ive-been-told-to-create-a-runnable-example-with-stack-snippets-how-do-i-do) snippet editor. – mplungjan Oct 07 '21 at 11:54
  • Just slice the part after the "T", and then it is like in the duplicate reference. – trincot Oct 07 '21 at 12:02

2 Answers2

0

Use Array.reduce

Logic

  • Loop through input with Array.reduce.
  • Get the time node from each category by splitting the sting on T.
  • Check if a node with same time exist in accumulator.
  • If yes, add the current value to the value of existing node.
  • Or else push a new node with value and category.

const data = {
  series: [
    { value: 1, category: "2021-03-04T04:00:00.000" },
    { value: 2, category: "2021-03-04T05:00:00.000" },
    { value: 3, category: "2021-03-04T06:00:00.000" },
    { value: 1, category: "2021-03-05T04:00:00.000" },
    { value: 2, category: "2021-03-05T05:00:00.000" },
    { value: 3, category: "2021-03-05T06:00:00.000" },
  ],
};
const result = data.series.reduce((acc, curr) => {
  const time = curr.category.split("T")[1];
  const accNode = acc.find((node) => node.category === time);
  if (accNode) {
    accNode.value += curr.value;
  } else {
    acc.push({ value: curr.value, category: time });
  }
  return acc;
}, []);
console.log({
  series: result,
});
Nitheesh
  • 19,238
  • 3
  • 22
  • 49
0

Map and reduce - you can split in the reduce but this is more readable

const data = {
  "series": [
  { "value": 1, "category": "2021-03-04T04:00:00.000" },
  { "value": 2, "category": "2021-03-04T05:00:00.000" },
  { "value": 3, "category": "2021-03-04T06:00:00.000" },
  { "value": 1, "category": "2021-03-05T04:00:00.000" },
  { "value": 2, "category": "2021-03-05T05:00:00.000" },
  { "value": 3, "category": "2021-03-05T06:00:00.000" }
  ]
}
const newData = data.series
  .map(item => ({value:item.value, category: item.category.split("T")[1]})) // cut the date off
  .reduce((acc,cur) => { 
    const item = acc.find(({category}) => category === cur.category); // find if we already have the time in the array we are creating
    if (item) item.value += cur.value; // if yes, add the value
    else acc.push(cur); // else push the current object
    return acc;
  },
  [])
console.log(newData)
mplungjan
  • 169,008
  • 28
  • 173
  • 236