DEV Community

Ana Laura
Ana Laura

Posted on • Edited on

5 1 1 1 1

E o reduce do JavaScript?

Olá pessoas! Meu objetivo com esse post é tentar ajudar no entendimento do famoso reduce().
Pode parecer um pouco confuso de início mas prometo tentar mostrar o poder desse método e como ele pode nos ajudar a resolver alguns problemas. 😻

O que é o reduce?

Em termos simples, o reduce() é uma função que recebe outra função como parâmetro, com o intuito de reduzir uma coisa em outra. Ele percorre cada elemento de um array, aplica uma função a esses elementos e acumula o resultado em um valor final. Esse valor final é o resultado da "redução" de todos os elementos do array. O valor final acumulado é retornado após todo o processo.

E os parâmetros do reduce?

Já falamos que o reduce recebe uma outra função como parâmetro, chamamos essa função de callback.
Essa callback é responsável por determinar como nossos elementos serão combinados. Além disso, a callback recebe alguns outros parâmetros, sendo eles:

  • Acumulador (accumulator): O valor acumulado resultante das ações anteriores.
  • Valor Atual (currentValue): O elemento atual do array sendo percorrido.
  • Índice Atual (currentIndex): O índice do elemento atual no array.
  • Array Original (array): O array original ao qual a função reduce() foi aplicada.

E também temos um segundo parâmetro, mas esse é opcional, que é o valor Inicial do Acumulador (initialValue).
Se a gente incluir ele nos parâmetros, a redução começa com esse valor. Se não fornecido, o primeiro elemento do array é quem assume essa posição de "valor inicial" e a redução começará a partir do segundo elemento.

Vamos pensar que estou percorrendo um array de números, primeiro vamos entender quem são o primeiro e o segundo parâmetro do reduce.

Um print de um código explicando o reduce, nesse código temos o reduce sendo aplicado a um array de números que recebe o nome de lista de números. Detalhamos também sobre cada parametro da callback passada para o reduce

Agora dê uma olhada nos parâmetros que a callback recebe:

Um print de um código explicando o reduce, nesse código temos o reduce sendo aplicado a um array de números que recebe o nome de lista de números. Detalhamos também sobre cada parametro do reduce

Reduzindo um array a um objeto com reduce 🙀

Agora que já entendemos os parâmetros do reduce vamos para a melhor parte: a prática!

Eu tenho uma lista com algumas frutas, onde alguma delas aparecem mais de uma vez. Observe:

const frutas = ['banana', 'maca', 'pera', 'banana', 'pera', 'abacaxi', 'pera', 'banana']
Enter fullscreen mode Exit fullscreen mode

Desafio: A ideia é pegar essa lista e descobrir quantas vezes cada um desses itens aparece, mostrando tudo bonitinho num objeto. Tipo assim:

{
  'banana': 3,
  'maca': 1,
  'pera': 3,
  'abacaxi': 1
}
Enter fullscreen mode Exit fullscreen mode

Primeiro, gostaria de propor resolver esse problema usando o famoso forEach.

const frutas = ['banana', 'maçã', 'pera', 'banana', 'pera', 'abacaxi', 'pera', 'banana'];

const contagemFrutas = {};
frutas.forEach(fruta => {
  if (contagemFrutas[fruta]) {
    contagemFrutas[fruta]++;
  } else {
    contagemFrutas[fruta] = 1;
  }
});

console.log(contagemFrutas);

Enter fullscreen mode Exit fullscreen mode

Dê uma olhada no código acima e tenta entender o que tá rolando! Logo abaixo eu dou uma explicação detalhada.

  1. Primeiro criamos um objeto vazio chamado contagemFrutas para armazenar as contagens de cada fruta.
  2. Depois utilizamos o forEach para percorrer cada elemento do array frutas. O forEach assim como reduce também recebe como parâmetro uma função que é executada para cada elemento do array.
  3. Dentro da função passada para forEach, verificamos se a fruta atual já existe como chave no objeto contagemFrutas.
  4. Se a fruta já existir no objeto contagemFrutas, incrementamos o valor correspondente a essa fruta.
  5. Caso a fruta ainda não exista no objeto contagemFrutas, criamos uma nova chave para essa fruta e atribuímos o valor inicial de 1.
  6. O processo acima vai repetir para cada fruta no array frutas, e no final teremos um objeto contagemFrutas contendo a contagem de cada tipo de fruta.

Por fim, usei o console.log para exibir o objeto contagemFrutas no console.

Agora que resolvemos o desafio usando o forEach(), bora ver resolver usando o reduce()!

Essa será a estrutura inicial do meu reduce. Vamos por partes!

frutas.reduce((acumulador, valorAtual) => {

}, {})
Enter fullscreen mode Exit fullscreen mode

Perceba que eu passo como valor inicial do meu reduce um objeto vazio. Isso é feito para que a gente possa pegar de volta esse objeto quando o reduce terminar. 🤓

Vamos continuar codando, mas antes dê um console.log() no acumulador e no valorAtual para conseguir visualizar melhor o retorno!

frutas.reduce((acumulador, valorAtual) => {
  console.log(acumulador);
  console.log(valorAtual);
  return acumulador
}, {})
Enter fullscreen mode Exit fullscreen mode

Você percebeu que o acumulador nos deu um objeto vazio? Isso acontece porque a gente começou ele assim na função reduce. Quando a gente joga um objeto vazio como o segundo parâmetro para a função reduce, ele é usado como valor inicial para o acumulador.

Bora continuar!

Lembra que quando usamos o forEach precisamos de uma condição para:

  1. Verificar se a fruta atual já existe como chave no objeto contagemFrutas.
  2. Se a fruta já existir no objeto contagemFrutas, incrementamos o valor correspondente a essa fruta.

No nosso reduce também precisamos fazer essa verificação, bora lá!

frutas.reduce((acumulador, valorAtual) => {
  if (acumulador[valorAtual]) {
    acumulador[valorAtual] ++
  } 
  return acumulador
}, {})
Enter fullscreen mode Exit fullscreen mode
  1. Primeiro, verificamos se a fruta atual (valorAtual) já existe como uma propriedade no objeto acumulador. Isso é feito verificando se acumulador[valorAtual] é verdadeiro (ou seja, se já existe). Se a fruta já existe no objeto, incrementa o valor da propriedade correspondente em 1 usando o operador de incremento ++.

Agora você deve tá se perguntando: Ana, e se não existir essa propriedade no objeto, o que fazemos?

frutas.reduce((acumulador, valorAtual) => {
  if (acumulador[valorAtual]) {
    acumulador[valorAtual]++
  } else {
    acumulador[valorAtual] = 1
  }
  return acumulador
}, {})
Enter fullscreen mode Exit fullscreen mode

Para isso adicionamos um else, caso não exista essa propriedade crie uma pra mim com o valor igual a 1!

E vualá !!! No final da iteração, o objeto acumulador é retornado para que seja usado como o acumulador na próxima iteração!

👀 Lembrando: Um objeto vazio é o nosso valor inicial do acumulador. Isso significa que, na primeira iteração, o objeto acumulador será vazio, mas à medida que as frutas são processadas, suas contagens serão todas armazenadas nesse objeto.

Se fornecermos como entrada o array de frutas abaixo, por exemplo:

const frutas = ['banana', 'maca', 'pera', 'banana', 'pera', 'abacaxi', 'pera', 'banana']
Enter fullscreen mode Exit fullscreen mode

Teremos como retorno/saída:

{ 
  banana: 3, 
  maca: 1, 
  pera: 3, 
  abacaxi: 1 
}
Enter fullscreen mode Exit fullscreen mode

Concluindo: Espero que este post tenha ajudado a esclarecer como usar o reduce() para resolver problemas como este.
O reduce é realmente poderoso em várias situações e pode ser incrivelmente útil.

Qualquer dúvida fiquem a vontade para comentar aqui, tentarei ajudar 💟

bjs bjs e até a próxima.

SurveyJS custom survey software

JavaScript UI Libraries for Surveys and Forms

SurveyJS lets you build a JSON-based form management system that integrates with any backend, giving you full control over your data and no user limits. Includes support for custom question types, skip logic, integrated CCS editor, PDF export, real-time analytics & more.

Learn more

Top comments (2)

Collapse
 
gpa1992 profile image
Gabriel Proença Araujo

Muito massa!

Collapse
 
analaura profile image
Ana Laura

Obrigada Gabriel, fico feliz que tenha gostado :)