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
.
Agora dê uma olhada nos parâmetros que a callback recebe:
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']
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
}
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);
Dê uma olhada no código acima e tenta entender o que tá rolando! Logo abaixo eu dou uma explicação detalhada.
- Primeiro criamos um objeto vazio chamado contagemFrutas para armazenar as contagens de cada fruta.
- 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.
- Dentro da função passada para forEach, verificamos se a fruta atual já existe como chave no objeto contagemFrutas.
- Se a fruta já existir no objeto contagemFrutas, incrementamos o valor correspondente a essa fruta.
- 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.
- 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) => {
}, {})
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
}, {})
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:
- Verificar se a fruta atual já existe como chave no objeto contagemFrutas.
- 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
}, {})
- 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
}, {})
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']
Teremos como retorno/saída:
{
banana: 3,
maca: 1,
pera: 3,
abacaxi: 1
}
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.
Top comments (2)
Muito massa!
Obrigada Gabriel, fico feliz que tenha gostado :)