Reducing an JavaScript Array of objects with dates as keys?

Viewed 85

The app I'm working with is outputting an array in javascript like this:

 let realData = [];
    realData.push({"2021-01-01":"5,000","2021-02-01":"5,000",
                  "2021-03-01":"5,000","2021-04-01":"5,000",
                  "2021-05-01":"5,000","2021-06-01":"5,000",
                  "2021-07-01":"5,000","2021-08-01":"5,000",
                  "2021-09-01":"5,000","2021-10-01":"5,000",
                  "2021-11-01":"5,000","2021-12-01":"5,000"});
    realData.push({"2021-01-01":"5,000","2021-02-01":"5,000",
                   "2021-03-01":"5,000","2021-04-01":"5,000",
                   "2021-05-01":"5,000","2021-06-01":"5,000",
                   "2021-07-01":"5,000","2021-08-01":"5,000",
                   "2021-09-01":"5,000","2021-10-01":"5,000",
                   "2021-11-01":"5,000","2021-12-01":"5,000"});
    realData.push({"2021-01-01":"5,000","2021-02-01":"5,000",
                   "2021-03-01":"5,000","2021-04-01":"5,000",
                   "2021-05-01":"5,000","2021-06-01":"5,000",
                   "2021-07-01":"5,000","2021-08-01":"5,000",
                   "2021-09-01":"5,000","2021-10-01":"5,000",
                   "2021-11-01":"5,000","2021-12-01":"5,000"});

console.log(realData);

Each line has 12 entries (for each month).

I'm looking at an effective way to cycle through them and sum the same month; combining each object so Jan 2021 would show 20,000 from the above.

I've previously used this code:

 var foo = _.chain(data)
            .groupBy('month')
            .map(function (objects, period) {
                return {
                    month: period,
                    value: _.sumBy(objects, item => Number(item.value)),

                };
            })
            .value();

which worked really well; but the data I'm using doesn't have named keys (i.e. before I had a JSON file that looked like this:

[
    {

        "month": "2020-06-01", 
        "value": "2500.00",
 
    }, ..

Is what I'm trying to achieve possible or do I need to revisit how the data is being stored?

2 Answers

When I have to do things like this I usually use the help of objects. See if this snippet helps you.

let test = [
        {"2021-01-01": "5,000", "2021-02-01": "5,000", "2021-03-01": "5,000", "2021-04-01": "5,000", "2021-05-01": "5,000"},
        {"2021-01-01": "5,000", "2021-02-01": "5,000", "2021-03-01": "5,000", "2021-04-01": "5,000", "2021-05-01": "5,000"},
        {"2021-01-01": "5,000", "2021-02-01": "5,000", "2021-03-01": "5,000", "2021-04-01": "5,000", "2021-05-01": "5,000"},
        {"2021-01-01": "5,000", "2021-02-01": "5,000", "2021-03-01": "5,000", "2021-04-01": "5,000", "2021-05-01": "5,000"}];

const sum = {};

test.forEach((line) => {
    Object.keys(line).forEach((key) => {
        if (!sum.hasOwnProperty(key)) {
            sum[key] = 0;
        }

        sum[key] += Number(line[key].replace(/,/g, ''));
    });
});

console.log(sum);

I took inspiration from gilberto and mine and made the most efficient one so far https://jsbench.me/4ckkefsg3b/1

let i = years.length;
while (i--) {
    const year = years[i];
    
    const keys = Object.keys(year);
    let m = keys.length;
    while (m--) {
        const month = keys[m];

        // Months value
        const value = + year[month].replace(/,/g, '');

        // Adds to current months total otherwise creates it
        sum[month] = sum[month] || 0 + value;
    }
}

Edit: I made some changes to the script making it 15% faster https://jsbench.me/9vkkfb3nzq/1

Related