How to add object properties in JavaScript?

9

Assume 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 by region? Is it possible to do this without loops?

The result would be an object like:

totais = {Norte:250, Sul:120}

The answers can be in pure JS or with libraries.

    
asked by anonymous 07.05.2014 / 17:01

3 answers

7

With the Underscore.js library 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 answer to the same question in SOEN (with solution generalization)

    
07.05.2014 / 18:22
5

To add 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 this:

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's left as:

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 bit complicated to do this without loops, as this will occur indirectly, because the input is dynamic.

    
07.05.2014 / 17:58
5

I got an even more synthetic way using 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();
    
07.05.2014 / 20:12