skip to Main Content

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}
]

2

Answers


  1. Chosen as BEST ANSWER

    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)
    

  2. 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);
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search