How to use the reduce (reduce) operation on objects?

4

In Javascript, when I need to do a reduction operation, I use the Array.reduce method.

So:

var valores = [1, 2, 3, 4, 5, 1000];

var resultado = valores.reduce(function (soma, atual) {
    return soma + atual;
})

console.log(resultado);

However, when I try to do with Array of objects, it does not work very well:

var valores = [{valor: 1}, {valor: 2}, {valor: 3}, {valor: 4}, {valor: 5}, {valor: 1000}];


var resultado = valores.reduce(function (soma, atual) {
        return soma.valor + atual.valor;
})

console.log(resultado);

In this case, it returns NaN .

But I'd like to be able to apply the reduction operation on an object to a specific attribute.

How to do this in Javascript?

    
asked by anonymous 13.11.2017 / 12:44

5 answers

6

In your first example you are not passing the initial value of the sum, you should do this, it is the second argument of .reduce(fn, valorInicial) . That part is the same in both examples.

The difference for an array of objects is just passing the property that has the number you need.

It would look like this:

var valores = [{valor: 1}, {valor: 2}, {valor: 3}, {valor: 4}, {valor: 5}, {valor: 1000}];
var resultado = valores.reduce(function(soma, atual) {
  return soma + atual.valor;
}, 0)

console.log(resultado);

In ES6 it would be:

var valores = [{valor: 1}, {valor: 2}, {valor: 3}, {valor: 4}, {valor: 5}, {valor: 1000}];
var resultado = valores.reduce(
    (soma, atual) => soma + atual.valor, 0
);

console.log(resultado);
    
13.11.2017 / 12:55
5

You forgot to pass the second parameter to the function reduce, which is the value that will start the operation, see:

var valores = [{valor: 1}, {valor: 2}, {valor: 3}, {valor: 4}, {valor: 5}, {valor: 1000}];

var resultado = valores.reduce(function (soma, atual) {
    return soma + atual.valor;
}, 0) // Inicia o valor de soma com 0

console.log(resultado); // 1015
    
13.11.2017 / 12:53
5

The first parameter will accumulate the sum, an option for your case is also indicate the initialization:

const valores = [{valor: 1}, {valor: 2}, {valor: 3}, {valor: 4}, {valor: 5}, {valor: 1000}];

const resultado = valores.reduce((a, b) => a + b.valor, 0);

console.log(resultado);
    
13.11.2017 / 12:52
3

It is necessary, first of all, to understand that in the function reduce the return of each execution / iteration will be used as the first parameter in the next iteration.

In the question code a number is returned in the first iteration, and in the next it is trying to access the valor property of this number.

You can return a new object that contains the value property and make it work the way you expect it to.

var valores = [{valor: 1}, {valor: 2}, {valor: 3}, {valor: 4}, {valor: 5}, {valor: 1000}];

var resultado = valores.reduce(function (soma, atual) {
  return { valor: soma.valor + atual.valor };
})

console.log(resultado);

You can also set an initial value for the sums

var valores = [{valor: 1}, {valor: 2}, {valor: 3}, {valor: 4}, {valor: 5}, {valor: 1000}];
    
var resultado = valores.reduce((soma, obj) => soma + obj.valor, 0);

console.log(resultado);
    
13.11.2017 / 12:51
2

I'll give you my straw too. Just use Object.keys to list the object keys.

var valores = [{valor: 1}, {valor: 2}, {valor: 3}, {valor: 4}, {valor: 5}, {valor: 1000}];

var resultado = Object.keys(valores).reduce(function (soma, key) {
    return soma + valores[key].valor;
}, 0)

console.log(resultado);

In my case, it only gave the expected result when I added the initial value, defined in the second parameter of reduce , with 0 .

    
13.11.2017 / 12:57