Adrian Iordache
Adrian Iordache

Reputation: 13

Aggregate array of objects by specific key and sum

I have the following array filled with some objects:

const data = [
    {date: '8 - 2021', 'a20 - plan1': 20, 'b70 - plan1': 10, 'c30 - plan1': 5},
    {date: '9 - 2021', 'a20 - plan1': 60, 'b70 - plan1': 70, 'c30 - plan1': 20},
    {date: '8 - 2021', 'a20 - plan1': 10, 'b70 - plan1': 5, 'c30 - plan1': 5},
    {date: '9 - 2021', 'a20 - plan1': 5, 'b70 - plan1': 5, 'c30 - plan1': 5}
];

And I would like to group by the date and sum the fields that are equal resulting in the following array:

const data = [
    {date: '8 - 2021', 'a20 - plan1': 30, 'b70 - plan1': 15, 'c30 - plan1': 10},
    {date: '9 - 2021', 'a20 - plan1': 65, 'b70 - plan1': 75, 'c30 - plan1': 25},
];

I would be glad if I could get any help, thanks in advance!

Upvotes: 1

Views: 1028

Answers (2)

Another solution can be separate into a hash map and then re-create a new array from it.

const data = [
    {date: '8 - 2021', 'a20 - plan1': 20, 'b70 - plan1': 10, 'c30 - plan1': 5},
    {date: '9 - 2021', 'a20 - plan1': 60, 'b70 - plan1': 70, 'c30 - plan1': 20},
    {date: '8 - 2021', 'a20 - plan1': 10, 'b70 - plan1': 5, 'c30 - plan1': 5},
    {date: '9 - 2021', 'a20 - plan1': 5, 'b70 - plan1': 5, 'c30 - plan1': 5}
];

const groupDataByDate = (array) => {
    const groups = {};
    
  // we create a hash map with the sum of each element grouping by date
    array.forEach(item => {
    const { date, ...props }  = item;
    
    if (!groups[date]) groups[date] = {};
    
    Object.keys(props).forEach(key => {
            if (!groups[date][key]) groups[date][key] = 0;
      
      groups[date][key] += item[key];
    })
  });
  

    // if we want to preserve as an array, we need to transform this hash map into the same array
    return Object.keys(groups).map(key => {
    return {
        date: key,
      ...groups[key], // this attribute contains the sums for each group
    };
  });
  
  // otherwise you can just return the groups
  // uncomment next line if the object helps you
  // return groups;
}

console.log(groupDataByDate(data));
/*
// expected result
const data = [
    {date: '8 - 2021', 'a20 - plan1': 30, 'b70 - plan1': 15, 'c30 - plan1': 10},
    {date: '9 - 2021', 'a20 - plan1': 65, 'b70 - plan1': 75, 'c30 - plan1': 25},
];
*/

Upvotes: 0

vaira
vaira

Reputation: 2270

using simple reduce can give you the solution. first, use a dictionary to insert the first set of unique 'date' as key and object as value, and when you find another matching date key, simply add current with the previous value saved in the dictionary.

const data = [
    {date: '8 - 2021', 'a20 - plan1': 20, 'b70 - plan1': 10, 'c30 - plan1': 5},
    {date: '9 - 2021', 'a20 - plan1': 60, 'b70 - plan1': 70, 'c30 - plan1': 20},
    {date: '8 - 2021', 'a20 - plan1': 10, 'b70 - plan1': 5, 'c30 - plan1': 5},
    {date: '9 - 2021', 'a20 - plan1': 5, 'b70 - plan1': 5, 'c30 - plan1': 5}
];

let dictionary = data.reduce((dic, value)=> { 
if(!dic[value.date])
{dic[value.date] = value; } else { 
    let old =  dic[value.date];
   Object.keys(old).forEach((key)=> { if(key != 'date') {   old[key] += value[key] } } ) 
  }      return dic } ,{});

let result = Object.values(dictionary);
console.log(result);

Upvotes: 1

Related Questions