Search code examples
javascriptarraysreactjsgrouping

Group array by two different keys and sum values


I'm working with an array on React and i'm trying to filter it by month and year, i managed to do it by month but for some reason i can't add the year key, this is what i have so far:

This is the array that i have originally:

paid = [
 {amount:155, month:11, year:2020, date:11-11-2020}
 {amount:120, month:11, year:2021, date:05-11-2021}
 {amount:135, month:12, year:2020, date:11-12-2020}
...
]

const group = groupBy(d, (invoices) => invoices.month); //d is the array called "paid"

This is the groupBy function:

function groupBy(list, keyGetter) {
    const map = new Map();
    list.forEach((item) => {
      const key = keyGetter(item);
      const collection = map.get(key);
      if (!collection) {
        map.set(key, [parseInt(item.amount)]);
      } else {
        collection.push(parseInt(item.amount));
      }
    });
    return map;
  }

And this is the result i have:

grouped = [
 {name:11, values: [155,120...]},
 {name:12, values: [135...]
];

And what i want to to is to also have it grouped by the year, so for example, the month 11, shouldn't have two values, because on the original array i have on month that's 11 from 2020 and one from 2021, so what i want to have as a result is this:

grouped = [
 {name:11/2020, values: [155...]},
 {name:11/2021, values: [120...]},
 {name:12/2020, values: [135...]
];

Can anyone help me with this?


Solution

  • If I understand correctly you want to sum all values per month per year. I guess this will work.

    // Generate random data.
    const genData = () => {
      const d = [];
      for(let i =0; i < 1000; i++) {
        d.push({
          year: Math.round(Math.random() * 10) + 2001,
          month: Math.round(Math.random() * 12),
          amount: Math.round(Math.random() * 100) + 100
        })
      }
      return d;
    };
    
    // Sum all data per month per year
    const sumData = (d) => {
      const summed = {};
      for(const {year,month,amount} of d) {
        // By using a unique key for each year/month combi you can easily access the
        // intermedeiate result and add another value.
        const key = year + '/' + month;
        
        // If it does not yet exist, create an empty record for this year/month
        if(!(key in summed)) {
          summed[key] = {year,month, sum:0, values:[]};
        }
        
        // Grab the intermediate values and add amount to sum and to values
        summed[key].values.push(amount)
        summed[key].sum += amount;
      }
      return Object.values(summed);
    };
    
    // Run all
    const d = genData();
    console.log(d);
    console.log(sumData(d));