Executando verificação de segurança...
4

Quem tem medo do reduce? Entenda esse método agora ou seu dinheiro de volta

O reduce é um método Javascript que reduz uma array para apenas um valor.

Isso é o que você já ouviu por aí.

peças quadradas de madeira formando a palavra diminution

Porque o reduce pode, com a mesma array, retornar um number, string, objeto, e também a própria array com apenas algumas alterações.


Escrevi no meu blog um post com quase tudo que você precisa saber sobre o método mais chatinho de todos:

  • Os parâmetros do reduce
    • A função callback
    • O valor inicial
  • O que acontece a cada iteração
  • O retorn da função callback do reduce
  • O reduce como substituto dos outros métodos de array
    • Map
    • Filter
    • Find
    • Every
    • Some
  • Os 4 parâmetros da função callback do reduce
    • acumulado
    • atual
    • index
    • array
  • Como saber que é o momento de usar o reduce?
    • Você precisa de um dado
    • Nenhum outro método de array consegue gerar esse dado
    • Você tem uma array em mãos

Vou deixar o link do post completo no meu blog aqui na fonte:

Carregando publicação patrocinada...
3

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).

6

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.

1

Muito legal esse bench.

Já tinha ouvido falar que o for simples é mais rápido que outras funções high order functions.

Mas ao mesmo tempo tem a questão da legibilidade e imutabilidade.

Legibilidade porque usar os métodos de array que já conhecemos (map, filter, find) é mais direto (e acho mais bonito no fim) do que o for simples. Isso não se aplica tanto ao reduce pq a lógica dele é diferente dos outros métodos.

E imutabilidade pq com um for simples tu sempre vai precisar declarar variável com let e ficar reatribuindo ela, então nesse caso prefiro criar tudo com const e criar os valores com os métodos que já mencionei.

O ponto que se perde é a performance, mas como tu falou, o for simples é 10 vezes mais rápido. Mas com arrays pequenas, que é o que o front-end trabalha, e que é sobre o que mais escrevo, tu nunca vai precisar lidar com uma array tão grande a ponto de isso ser notável.