Group and accumulate values in JavaScript

2

Dear:

I have the following file JSON with information:

var rawtData = [
    { date: "2015-01-03", "pv": 50, "ac": 100, "ev": 50 },
    { date: "2015-01-01", "pv": 100, "ac": 200, "ev": 200 },                                
    { date: "2015-01-02", "pv": 200, "ac": 100, "ev": 150 },                
    { date: "2015-01-03", "pv": 300, "ac": 400, "ev": 200 },                
    { date: "2015-01-03", "pv": 50, "ac": 50, "ev": 200 },
    { date: "2015-01-02", "pv": 200, "ac": 100, "ev": 50 },
    { date: "2015-01-01", "pv": 50, "ac": 100, "ev": 50 },
    { date: "2015-01-03", "pv": 10, "ac": 60, "ev": 50 },
    { date: "2015-01-01", "pv": 70, "ac": 50, "ev": 50 },
    { date: "2015-01-03", "pv": 400, "ac": 350, "ev": 300 }
];

and I need to accumulate the values of pv , ac and ev per day (in this example) as the following result shows:

resultData = [
    { "date": "2015-01-01", "pv": 220, "ac": 350, "ev": 300 },
    { "date": "2015-01-02", "pv": 400, "ac": 200, "ev": 200 },
    { "date": "2015-01-03", "pv": 810, "ac": 960, "ev": 800 },
];

As I am a newbie in JavaScript and I was asked for the job, I could only get this piece of code that allows me to group data but I can not do the aforementioned summation:

Array.prototype.groupBy = function (prop) {
    return this.reduce(function(groups, item) {
        var val = item[prop];
        groups[val] = groups[val] || [];
        groups[val].push(item);
        return groups;
     }, {});
}

Someone could help me understand how to modify this code or if you have some other algorithm I will be very grateful.

    
asked by grandtjs 22.02.2017 в 22:33
source

1 answer

2

The group by of a Array , as you have stated, will always have the shape of an object whose keys are the values of the field you are grouping.

Modifying your groupBy function a bit:

var rawtData = [
    { date: "2015-01-03", "pv": 50, "ac": 100, "ev": 50 },
    { date: "2015-01-01", "pv": 100, "ac": 200, "ev": 200 },
    { date: "2015-01-02", "pv": 200, "ac": 100, "ev": 150 },
    { date: "2015-01-03", "pv": 300, "ac": 400, "ev": 200 },
    { date: "2015-01-03", "pv": 50, "ac": 50, "ev": 200 },
    { date: "2015-01-02", "pv": 200, "ac": 100, "ev": 50 },
    { date: "2015-01-01", "pv": 50, "ac": 100, "ev": 50 },
    { date: "2015-01-03", "pv": 10, "ac": 60, "ev": 50 },
    { date: "2015-01-01", "pv": 70, "ac": 50, "ev": 50 },
    { date: "2015-01-03", "pv": 400, "ac": 350, "ev": 300 }
];

var groupBy = function (miarray, prop) {
    return miarray.reduce(function(groups, item) {
        var val = item[prop];
        groups[val] = groups[val] || {date: item.date, pv: 0, ac: 0,ev: 0};
        groups[val].pv += item.pv;
        groups[val].ac += item.ac;
        groups[val].ev += item.ev;
        return groups;
    }, {});
}

console.log(groupBy(rawtData,'date'));

You'll see that the output is

{
  "2015-01-03": {
    "date": "2015-01-03",
    "pv": 810,
    "ac": 960,
    "ev": 800
  },
  "2015-01-01": {
    "date": "2015-01-01",
    "pv": 220,
    "ac": 350,
    "ev": 300
  },
  "2015-01-02": {
    "date": "2015-01-02",
    "pv": 400,
    "ac": 200,
    "ev": 200
  }
}

It means that you can get the values by applying Object.values on the output:

var resultData = Object.values(groupBy(rawtData,'date'));

Edit: In the snippet I left a function that does the same thing without getting into modifying the Array prototype. Modifying native prototypes is a poor practice .

    
answered by 22.02.2017 в 22:44