How to add object properties in Javascript?

Asked

Viewed 1,021 times

9

Suppose an object as follows:

vendas = {
    obs1:{
        Venda1:{Regiao:"Norte", Valor: 200}, 
        Venda2:{Regiao:"Sul", Valor:100}
    }, 
    obs2:{
        Venda1:{Regiao:"Norte", Valor: 50}, 
        Venda2:{Regiao:"Sul", Valor:20}
    }
}

How to add the sum of values per region? It is possible to do this without loops?

The result would be an object like:

totais = {Norte:250, Sul:120}

Answers can be in pure JS or with libraries.

  • 3

    Are you up to using a library? Underscore greatly simplifies the solution.

  • Of course, what I want in the background is to find libraries that facilitate data manipulation in JS. But to ask that would be very open, so I thought I’d give an example!

  • Well, I got in late and I already got a good response with underscore. But I thought the code would be more concise using this library... Compared to the pure JS code, I think I would end up using the second.

3 answers

7


With the library Underscore.js you can do something like this:

var totais = _
    .chain(vendas)
    // Primeiro: "achatar" as vendas
    .map(function(v) { 
        return _
            .chain(v)
            .map(function(v2) {
                return v2;
            })
            .value(); 
    })
    .flatten()
    // Segundo: agrupar as vendas por região
    .groupBy('Regiao')
    // Terceiro: somar os agrupamentos e criar o objeto com os totais
    .map(function(g, key) {
        return {
            type: key, 
            val: _(g).reduce(function(m, x) {
                return m + x.Valor;
            }, 0)
        };
    })
    .value();

console.log(totais);

Example in jsFiddle

mgibsonbr’s answer to the same question in SOEN (with generalization of the solution)

  • 2

    Good solution, but why call value just to have to use _() again? http://jsfiddle.net/mgibsonbr/4Dbaq/1/

  • Yeah, that’s better! The guys were waiting for me for lunch here, I did it running! Hehehe.. (I’ll update reply)

  • All right, man, thanks a lot! I asked this question on the SOEN if you would like to answer there: http://stackoverflow.com/questions/23521894/how-to-aggregate-objects-properties . PS: SOPT is much better and more receptive than English, we have to keep it that way.

  • I translated that answer and posted on Soen, assigning the source here and adding my own contributions (i.e. generalizing the solution). I agree that Sopt is even more receptive, although reading the comments there I found that some of them do have some merit (particularly this).

  • Very interesting your generalization, congratulations!

  • @mgibsonbr I don’t know if I agree. Some answers will naturally be more generalizable than others the important thing is to solve the problem. For example, I didn’t have to explain that I want a generalizable answer here at Sopt and there came both a more flexible response and a less, and both bring useful information. I think I find this SOEN survey productive, and they considered closing the question before they even let interesting answers arise.

  • @Carloscinelli I agree, sometimes one spends too much time discussing whether the question is appropriate to the site, when energies would be better spent answering the question... What I said had merit is the questioning of what is actually being asked: is the presence or not of a functional/declarative form? ("do without loops") Generalization according to structure? (nesting levels, property names) Something else? Here at Sopt we understood quickly what you wanted, but maybe there they did not find the question clear enough.

  • @mgibsonbr am having trouble testing its "Aggregate" function, it is not finding the "Flatten" function (error: Uncaught Referenceerror: Flatten is not defined). It will be problem of scope?

  • 1

    @Carloscinelli I tested in jsFiddle before posting on Soen, only I didn’t publish the fiddle because I was too lazy to translate into English... : P http://jsfiddle.net/mgibsonbr/4Dbaq/2/ P.S. Ah, it is: after editing - that changed the name of the function to deepFlatten - I forgot to change in a part. It’s already fixed!

Show 4 more comments

6

To aggregate the values you can use the following function:

function somarRegioes(vendas)
{
    totais = {};

    obs = Object.keys(vendas).map(function (key1) 
    {
        var obs_vendas = vendas[key1];

        Object.keys(obs_vendas).map(function (key2) 
        {
            var regiao = obs_vendas[key2]['Regiao'];

            // Se a região ainda não existir em totais.
            if(totais[regiao] === undefined) 
                totais[regiao] = 0;

            totais[regiao] += obs_vendas[key2]['Valor'];
        });
    });

    return totais;
}

Or with that:

function somarRegioes(vendas)
{
    totais = {};

    for(var obs in vendas)
    {
        for(var venda in vendas[obs])
        {
            var regiao = vendas[obs][venda]['Regiao'];

            // Se a região ainda não existir em totais.
            if(totais[regiao] == undefined) 
                totais[regiao] = 0;

            totais[regiao] += vendas[obs][venda]['Valor'];
        }
    }

    return totais;
}

What turns out to be:

vendas = {obs1:{Venda1:{Regiao:"Norte", Valor: 200}, Venda2:{Regiao:"Sul", Valor:100}}, obs2:{Venda1:{Regiao:"Norte", Valor: 50}, Venda2:{Regiao:"Sul", Valor:20}}}
resultado = somarRegioes(vendas); // output = Object {Norte: 250, Sul: 120}

I find it a little complicated to do this without loops, because it will occur even indirectly, because the input is dynamic.

5

I got an even more synthetic shape using the jFunk and Underscore.

totais = _.chain(jF("*[Regiao]", vendas).get()).groupBy('Regiao').map(function(g, key) {
        return {
            type: key, 
            val: _(g).reduce(function(m, x) {
                return m + x.Valor;
            }, 0)
        };
    })
    .value();
  • Interesting this jFunk, in fact JSON (and JS objects) needed a selection syntax just like Xpath is for XML. Too bad it’s still just a prototype (or proof-of-concept), let’s hope it goes forward!

Browser other questions tagged

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