Como saber que é o momento de usar o reduce?
Quando um simples for
não resolve o problema muito bem, e até melhor, e quase sempre ele resolve.
E quando não liga para eficiência.
E ainda não tem nada complexo para reduzir. Mesmo se passar de uma condição extremamente simples já não compensa.
As pessoas estão se enfiando muito em postagens na internet que ensinam receitas de bolo sem discutir todas as questões e sem entendimento de todo o processo da computação, e adotando coisas por modinha. O reduce()
tem seu lugar, mas é bem menos do que a maioria das pessoas hoje acham.
Claro, onde o resto do código está mal pensado, usá-lo em qualquer situação não fará mais mal.
Espero ter ajudado.
Farei algo que muitos pedem para aprender a programar corretamente, gratuitamente. Para saber quando, me segue nas suas plataformas preferidas. Quase não as uso, não terá infindas notificações (links aqui).
Complementando, tem o detalhe (que pode ou não fazer diferença dependendo do caso) do reduce
ser mais lento, justamente porque precisa fazer várias chamadas de função (afinal, o parâmetro que vc passa para ele é uma função que é chamada para cada elemento).
Claro que para poucos arrays pequenos a diferença é insignificante, mas é algo a se considerar se estiver processando grandes volumes de dados. Fiz um teste simples no JSBench.ME, e também no Node usando o Benchmark.js:
var Benchmark = require('benchmark');
var suite = new Benchmark.Suite;
// cria um array bem grande, com números aleatórios entre 1 e 1000
var array = [];
for (var i = 0; i < 1000000; i++) {
array[i] = Math.floor(Math.random() * 1000);
}
suite
.add('for simples', function () {
let soma = 0;
for (var i = 0; i < array.length; i++) {
soma += array[i];
}
})
.add('for of', function () {
let soma = 0;
for (var n of array) {
soma += n;
}
})
.add('reduce', function () {
let soma = array.reduce((a, b) => a + b);
})
.on('complete', function () {
console.log('Fastest is ' + this.filter('fastest').map('name'));
})
.on('cycle', function (event) {
console.log(String(event.target));
})
.run({
'async': true
});
Basicamente, criei um array com 1 milhão de números e calculei a soma deles. Usei o for
"tradicional", o for..of
e o reduce
, e o resultado foi:
for simples x 1,434 ops/sec ±1.68% (90 runs sampled)
for of x 968 ops/sec ±1.18% (93 runs sampled)
reduce x 168 ops/sec ±0.84% (86 runs sampled)
Fastest is for simples
Os números representam a quantidade de operações por segundo ("ops/sec", ou seja, quanto maior, mais rápido). O for
tradicional foi cerca de 10 vezes mais rápido (fez quase 10 vezes mais operações por segundo que o reduce
). O for of
é um pouco mais lento, porque internamente usa o protocolo de iteradores que tem um custo um pouco maior, mas ainda sim é melhor que reduce
. Rodei mais algumas vezes, variando o tamanho do array, e os resultados foram similares. No JSBench.ME os resultados também foram parecidos (pode variar de acordo com o browser).
Como já dito, se forem poucos arrays pequenos, a diferença será imperceptível. Mas ainda tem os outros fatores já mencionados, de que um loop simples resolve melhor a maioria dos casos. Já vi muita gente forçando o uso de reduce
e deixando o código pior e mais confuso. Ele é útil sim, mas nem sempre é a solução mais adequada.