-1

I have an array of objects that looks like this:

[
{date: '2022-12-07', type: 'freeze', value: 3},
{date: '2022-12-06', type: 'freeze', value: 1},
{date: '2022-12-05', type: 'freeze', value: 1},
{date: '2022-12-04', type: 'boil',   value: 1},
{date: '2022-12-04', type: 'freeze', value: 1},
{date: '2022-12-05', type: 'steam',  value: 5}
]

I'd like to create an array of objects that combines all distinct types to become a key with the corresponding value for each distinct date so the types with no value in a given date will show as 0 with a total sum. The type(s) can vary from set to set, and I'd want only the found ones in the set to be present so the output looks like this:

This is a different question than what was raised here: Most efficient method to groupby on an array of objects because part of what I'm looking to do is to turn all the values of the key 'type' into keys for each date with corresponding values as the value of the key. So this needs remapping along with grouping.

[
{date: '2022-12-04', freeze: 1, boil: 1, steam: 0, total: 2},
{date: '2022-12-05', freeze: 1, boil: 0, steam: 5, total: 6},
{date: '2022-12-06', freeze: 1, boil: 0, steam: 0, total: 1},
{date: '2022-12-07', freeze: 3, boil: 0, steam: 0, total: 3}
]
cmgchess
  • 7,996
  • 37
  • 44
  • 62
user3302967
  • 149
  • 1
  • 1
  • 5
  • adding to the answer in linked . you can create a set of unique titles and create an object with 0s in it and pass it in the accumulator – cmgchess Apr 18 '23 at 15:51
  • I'm not seeing an example solution in the linked answer that is helping me get started. Kinda surprised this question was closed since it's pretty different than the one I'm told is a duplicate. – user3302967 Apr 18 '23 at 16:13
  • the question has reopened do you have the answer already – cmgchess Apr 20 '23 at 14:50
  • Yes - you helped me get started with a workable solution that I have working now. Thank you. – user3302967 Apr 20 '23 at 16:08

2 Answers2

1

If we break it down, you could achieve the result by;

  1. Create a map where the key is the date, and the value is an object where it has the keys from the type and total.
  2. Iterate through the original array, and use it as data source to perform operations to the map above.
  3. Once all original array's elements are processed, output the object to your desired result.

var arr = [
  {date: '2022-12-07', type: 'freeze', value: 3},
  {date: '2022-12-06', type: 'freeze', value: 1},
  {date: '2022-12-05', type: 'freeze', value: 1},
  {date: '2022-12-04', type: 'boil',   value: 1},
  {date: '2022-12-04', type: 'freeze', value: 1},
  {date: '2022-12-05', type: 'steam',  value: 5}
];

// 1. Create a map where the key is the date, and the value is an object where it has the keys from the `type` and `total`.
var obj = {};

// 2. Iterate through the original array, and use it as data source to perform operations to the map above.
arr.forEach((elem) => {
  const { date: key, type, value } = elem;
  
  // If obj[key] doesn't exist - create it.
  if (!obj[key]) {
    obj[key] = {
      freeze: 0,
      boil: 0,
      steam: 0,
      total: 0
    };
  }
  
  // If obj[key][type] exists, increment it with the `value`
  if (obj[key].hasOwnProperty(type)) {
    obj[key][type] += value;
  }

  // If obj[key]['total'] exists, increment it with the `value`
  if (obj[key].hasOwnProperty('total')) {
    obj[key]['total'] += value;
  }
});

// Transform obj into the desired output.
var result = Object.keys(obj).map((key) => Object.assign({
  date: key
}, obj[key]));

// Log to visualize the output.
console.log(result);
choz
  • 17,242
  • 4
  • 53
  • 73
1

This is another method suggested by @cmgchess that works well, and enables dynamic keys.

const input = [   {date: '2022-12-07', type: 'freeze', value: 3},    {date: '2022-12-06', type: 'freeze', value: 1},   {date: '2022-12-05', type: 'freeze', value: 1},    {date: '2022-12-04', type: 'boil',   value: 1},    {date: '2022-12-04', type: 'freeze', value: 1},    {date: '2022-12-05', type: 'steam',  value: 5},]

const uniqTitles = [...new Set(input.map(x => x.type))]
const titleAccumulator = uniqTitles.reduce((obj, type) => ({...obj, [type]: 0}), {});

const res = Object.values(input.reduce((acc,{date,type,value}) => {
  acc[date]??={date,total:0,...titleAccumulator}
  acc[date][type]+=value
  acc[date].total+=value
  return acc
},{}))

console.log(res)
user3302967
  • 149
  • 1
  • 1
  • 5