Javascript - Soma e Group By em Array

Asked

Viewed 625 times

3

I would like a tip/help.

I’m working with a number of files JSON, and applying filters to them as the user advances in the system.

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

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

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

Okay, the filter is applied, comfort the marker I need, at this point 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 to simplify, 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

Researching, I saw that can be done through the .reduce(), I found some examples, but I could not apply any, I am layman in the subject.

I found this link: sum-and-group-by-of-json-data, it applies on a column only, as I would for 4 for example, adding up my columns?

Example of the link:

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.

  • To do these types of operations I use the jLinq library, see if it helps you! Not very good documentation, but it’s very useful.

  • @Fernando took one look at this library.. It sounds interesting, but since only at this point will I use this consolidation, I’m trying to do it with . reduce().. Last I’ll try with jLink. Thank you.

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 only remains to instantiate, pass the data and get the grouped items.

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);
  • Bruno, excellent. I did a test here, I’m getting an error message. Analyzing a little more, I put to print the currentItem, the array has 3 objects, it is printing the 3 and 2 more ghosts(undefined), and I get the error: Uncaught TypeError: Cannot read property 'UF' of undefined. How can I treat?

  • Appears this way: (Each // Jumps line) Object {UF: "TO", DESC_CLUSTER: "PALMAS", QNTD1: 0, QNTD2: 0} // Object {UF: "TO", DESC_CLUSTER: "PALMAS", QNTD1: 1, QNTD2: 1} // Object {UF: "TO", DESC_CLUSTER: "PALMAS", QNTD1: 2, QNTD2: 2} // Object {UF: undefined, DESC_CLUSTER: undefined, QNTD1: 0, QNTD2: 0} // Object {UF: undefined, DESC_CLUSTER: undefined, QNTD1: 0, QNTD2: 0}

  • Um, weird... Jsfiddle with the situation, Fernando? I believe it will be easier for us to reach a solution.

  • Anyway, I see that it is necessary to check if the object has the properties before reading them (using Reflection: Object.hasOwnProperty('NOME_DA_PROPRIEDADE') ), if there is no guarantee of the existence of certain properties. In addition, of course, to checking if it’s valid. I didn’t do any of this to simplify the code, but recommend the implementation.

  • Bruno, I’m going to try to implement this. I’m a layman, but I understand what it takes. If I can’t, I create a Jsfiddle with an example. Thanks again.

  • I made a Jsfiddle, it’s not grouping right, I must have done something wrong, you could take a look? jsfiddle-Fernando. You are printing the table on the console. Thank you.

  • I could only look now. I was slow but corrected =) I updated my answer with the correction and added a quote with a brief explanation.

  • I have updated your fiddle with code correction and script references

  • Man, sensational. Thank you so much for your help, I owe you a hahahaha. Thank you very much.

Show 4 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.