Javascript - Sum and Group By in Array

3

I would like a tip / help.

I'm working with a series of JSON files, and applying filters to them as the user progresses through the system.

So far so good, I managed to do it quietly using .filter() .

My problem is in the next step to this one. I need to apply the filter in this file, and with the filter result, summarize the information based on some columns only.

var as=$(ards).filter(function (i,n){
    return n.ARMARIO_ERB===marker.getTitle();
});

OK, the filter is applied, configures the marker I need, at this point I print the filter information:

for (var i=0;i<as.length;i++){
    conteudo_info +=    "<tr>" +
                          "<td>" + as[i].UF + "</td>" +
                          "<td>" + as[i].DESC_CLUSTER + "</td>" +
                          "<td>" + as[i].DESC + "</td>" +
                          "<td>" + as[i].QNTD1+ "</td>" +
                          "<td>" + as[i].QNTD2+ "</td>" +
                        "</tr>" ;
}

I put five columns just for simplicity, I have around 10.

What I need to do is instead of presenting the 10 columns, I would like to present the result in a consolidated way.

Example (Original Base):

PR CTBA  A 1 1
PR CTBA  B 8 5
PR MGA   A 1 2
PR CTBA  C 2 0

Consolidated:

PR CTBA 11 6
PR MGA  1  2

Searching, I saw that it can be done through .reduce() , I found some examples, but I could not apply any, I'm a layman.

I found this link: sum-and-group-by-of-json-data , it applies over a column just, how would I do for 4 for example, adding my columns?

Link example:

var result = dataObject.reduce(function(res, obj) {
    if (!(obj.category in res))
        res.__array.push(res[obj.category] = obj);
    else {
        res[obj.category].hits += obj.hits;
        res[obj.category].bytes += obj.bytes;
    }
    return res;
}, {__array:[]}).__array
                .sort(function(a,b) { return b.bytes - a.bytes; });

Thank you.

    
asked by anonymous 11.02.2016 / 17:11

1 answer

2

I implemented a solution with 'Vanilla JS' (pure Javascript: p).

Follows:

//Classe de agrupamento
function Foo(){
    // data source
    this.data = [];

    // retorna um array de objetos agrupados por propertyNames
    // propertyNames [array de string] - nomes das propriedades de agrupamento
    this.getGroupedData = function(propertyNames){
        if(!this.data.length || !propertyNames || !propertyNames.length) return [];

        var group = [], currentIndex, currentItem;

        for(var i in this.data){
            currentIndex = getGroupedItemIndex(group, propertyNames, this.data[i]);
            if(currentIndex >= 0){
                currentItem = group[currentIndex];
            }else{
                currentItem = {};
                for(var pi in propertyNames){
                    currentItem[propertyNames[pi]] = this.data[i][propertyNames[pi]];
                }
                currentItem.TOTAL_QNTD1 = 0;
                currentItem.TOTAL_QNTD2 = 0;
            }

            currentItem.TOTAL_QNTD1 += this.data[i].QNTD1;
            currentItem.TOTAL_QNTD2 += this.data[i].QNTD2;

            if(currentIndex >= 0){
                group[currentIndex] = currentItem;
            }else{
                group.push(currentItem);
            }
        }

        return group;
    }

    var getGroupedItemIndex = function(array, propertyNames, targetItem){
        var index = -1, found = true;

        for(var i in array){        
            for(var pi in propertyNames){
                found &= (array[i][propertyNames[pi]] === targetItem[propertyNames[pi]]);
            }
            if(found){
                index = i;
                break;
            }               

             // reset do valor para a próxima iteração
             found = true;
        }

        return index;
    }
}

Now all you have to do is instantiate, pass the data and get the items grouped together.

var foo = new Foo();
foo.data = [{UF: 'PR', DESC_CLUSTER: 'CTBA', DESC: 'A', QNTD1: 1, QNTD2: 1}, {UF: 'PR', DESC_CLUSTER: 'CTBA', DESC: 'B', QNTD1: 8, QNTD2: 5}, {UF: 'PR', DESC_CLUSTER: 'MGA', DESC: 'A', QNTD1: 1, QNTD2: 2}, {UF: 'PR', DESC_CLUSTER: 'CTBA', DESC: 'C', QNTD1: 2, QNTD2: 0} ];

// obtém os dados agrupados por UF e DESC_CLUSTER
var groupedData = foo.getGroupedData(['UF', 'DESC_CLUSTER']);
//para melhor visualização no console: table(groupedData);
    
11.02.2016 / 20:08