image

Acesse bootcamps ilimitados e +650 cursos pra sempre

60
%OFF
Antonio Guedes
Antonio Guedes21/03/2025 11:25
Compartilhe
Nexa - Análise Avançada de Imagens e Texto com IA na AWSRecomendados para vocêNexa - Análise Avançada de Imagens e Texto com IA na AWS

Como Agregar Dados de Forma Eficiente em JavaScript - Dominando o reduce()

    📌Introdução

    Durante o desenvolvimento de software, muitas vezes precisamos agregar relatórios 📊 que resumem e estruturam dados de forma clara. Isso facilita tanto o entendimento do usuário quanto a tomada de decisões 🤔.

    const clientes = [
    {nome: 'Ana', idade: 25, cidade: 'São Paulo', sexo: 'F'},
    {nome: 'Fernando', idade: 44, cidade: 'São Francisco do Conde', sexo: 'M'},
    {nome: 'João', idade: 19, cidade: 'São Chapadinha', sexo: 'M'},
    {nome: 'Bernardo', idade: 31, cidade: 'Brasília', sexo: 'M'},
    {nome: 'Júlia', idade: 27, cidade: 'Rio de Janeiro', sexo: 'F'},
    ]
    

    Se o usuário precisar entender quantos clientes existem em cada cidade ou qual a distribuição por gênero, ele terá dificuldades ao analisar os dados dessa forma.

    Felizmente, com o método reduce(), podemos transformar essa estrutura de dados em um formato mais organizado e legível, facilitando sua análise. 

    📌O que faz o método reduce()?

    O método reduce() é uma função de alta ordem em JavaScript que permite percorrer um array e acumular seus valores de acordo com uma lógica definida pelo programador. Seu principal objetivo é reduzir um conjunto de dados a um único valor ou estrutura, que pode ser um número, string, array ou objeto.

    No exemplo mencionado na introdução, queremos agrupar os clientes por gênero. Para isso, podemos utilizar reduce() para transformar a lista de clientes em um objeto que contém a contagem de pessoas do gênero masculino e feminino, ignorando outras informações como nome, idade e cidade.

    O resultado esperado seria:

    {clientePorGenero: {masculino: 3, feminino: 2}}
    

    🧑‍🎓Como aprendi o método?

    Ao iniciar no desenvolvimento, percebi que entender lógica de programação e estrutura de dados era fundamental, especialmente para lidar com respostas vindas do banco de dados e retornos de métodos que envolvem diferentes formatos de dados.

    Foi então que decidi usar a IA ChatGPT para me ajudar a melhorar nesse aspecto, começando pelos arrays. Durante a conversa, a IA me desafiou a somar os itens de um array e, instintivamente, tentei usar forEach(). Foi nesse momento que recebi a sugestão de usar reduce(), um método que eu ainda não dominava.

    A partir daí, fui recebendo desafios progressivamente mais complexos, simulando problemas do dia a dia de um desenvolvedor. Com cada exercício, fui compreendendo melhor a utilidade do reduce() e sua aplicação prática em problemas reais.

    seuArray.reduce((acumulador, valorAtual, índice, arrayOriginal) => {
    
               // Lógica de acumulação
    
    }, valorInicial)
    

    O reduce() sempre retorna um valor, que pode ser um número, string, objeto ou até mesmo um array. Esse retorno precisa ser armazenado para ser utilizado posteriormente.

    🤔Quais argumentos o reduce() recebe?

    Acumulador: O valor que é atualizado a cada iteração.

    Valor atual: O item atual do array sendo processado.

    Índice (opcional): A posição do item dentro do array.

    Array original (opcional): O array completo sobre o qual o reduce() está sendo executado.

    Valor inicial (opcional): Define o valor inicial do acumulador. Se não for informado, o primeiro item do array será usado como valor inicial.

    O valor inicial é importante porque determina o formato da saída. Se for um objeto {}, o resultado será um objeto; se for um array [], o retorno será um array; se for 0, o resultado será um número acumulado.

    O reduce() é especialmente útil para resumir e transformar dados, como no caso de um array de objetos, onde ele pode agregar informações de forma estruturada.

    📌Sintaxe básica

    A sintaxe básica do reduce envolve sempre a presença de um acumulador e um valor atual, importante para evitar bugs a inicialização do acumulador para evitar retornos inesperados. 

    let max = [0, 1, 2, 3, 4, 5].deduce(function(acc, valorAtual){
    
    if(acc > valorAtual) {acc = acc}
    
    else{acc = valorAtual}
    
    return acc
    }, 0)
    

    📝Explicação:

    •  A função de callback recebe dois parâmetros:
    • acc (acumulador): Armazena o maior valor encontrado até o momento;
    • valorAtual: O número atual do array que está sendo analisado.
    • A cada iteração, o código verifica se acc é maior que valorAtual:
    • Se for, acc mantém seu valor.
    • Caso contrário, acc assume o valor de valorAtual.
    • Ao final, reduce() retorna o maior valor encontrado, que será armazenado na variável max.Parâmetros (accumulator, currentValue, index, array)

    Neste exemplo, que apenas muda a função de call-back, no exemplo anterior apenas compara os valores entre o acc e o valorAtual, neste exemplo, adiciona ao acc, que está inicializado com 0, o valorAtual, gerando uma soma a cada iteração.

    Uma aplicação prática para esta soma usando reduce seria calcular o total de vendas em um sistema de e-commerce.

    Imagine que você tenha um array apresentando compras realizadas, onde cada item tem um valor:

    const vendas = [100, 250, 75, 300, 150];
    
    const totalVendas = vendas.reduce((acc, valorAtual) => acc + valorAtual, 0)
    
    console.log(`Total de vendas: R$ ${totalVendas}`)
    
    
    
    //saída: Total de vendas R$ 875
    

    📝Explicação:

    • O acumulador (acc) começa com 0;
    • A cada iteração valorAtual (o valor de uma venda) é somado ao acc;
    • No final, reduce() retorna a soma total das vendas, que pode ser exibida para um administrador da loja.

    Observação importante: Esse mesmo conceito pode ser aplicado para calcular despesas, notas de alunos, pontos de um jogo.

    📌Reduce() na Prática: Agregando dados Complexos

    É possível realizar agrupamentos de dados em um objeto por uma de suas propriedades. Veja o exemplo que segue:

    let pessoas = [
             { nome: “Rosana”, idade: 20},
             { nome: “Max”, idade: 22},
             { nome: “Jane”, idade: 20},
    ]
    function agruparPor(objetoArray, propriedade){
    return objetoArray.reduce((acc, obj) => {
      let key = obj[propriedade];
      if(!acc[key]){acc[key] = [];}
      acc[key].push(obj);
      return acc;
      }, {});
    }
    let grupoDePessoas = agruparPor(pessoas, “idade”)
    
    //Saída
    //grupoPessoas é:
    //{
    //        20: [
    //                        {nome: “Rosana”, idade: 20},
    //                        {nome: “Jane”, idade: 20},
    //             ], 
    //        22:[{nome: “Max”, idade: 22}]
    //}
    

    🤯Introdução de um problema real 

    Somando Faturamento Mensal 📊

    Imagine que você trabalha para uma empresa que quer analisar seu faturamento mensal. Então você deve somar o total de faturamento para cada mês e apresentar o resumo.

    const transações = [
             {mes: “Janeiro”, valor: 1000}, 
             {mes: “Fevereiro”, valor: 1500}, 
             {mes: “Janeiro”, valor: 500}, 
             {mes: “Março”, valor: 2000}, 
             {mes: “Fevereiro”, valor: 1000}, 
    ];
    
    function relatorioFaturamento(transacoes){
             return transações.reduce((acc, transacao) => {
                  const { mes, valor } = transação
                  acc[mes] = acc[mes] ? acc[mes] + valor : valor;
                  return acc;
      }, {});
    }
    console.log(relatoriaFaturamento(transações))
    // Saída: { Janeiro: 1500, Fevereiro: 2500, Março: 2000 }
    

    Contar Frequência de Clientes 👀

    Imagina que você quer saber qual é o cliente mais frequente de teu e-commerce. Você tem um array com as compras realizadas:

    const compras = [
             {id: 101, cliente: “Maria Aparecida”, email: “maria.aparecida@email.com”},
             {id: 202, cliente: “Paulo Augusto”, email: “augustos@email.com”},
             {id: 101, cliente: “Maria Aparecida”, email: “maria.aparecida@email.com”},
             {id: 303, cliente: “Raissa Loureto”, email: “louretinho@email.com”},
             {id: 202, cliente: “Paulo Augusto”, email: “augustos@email.com”},
             {id: 101, cliente: “Maria Aparecida”, email: “maria.aparecida@email.com”},
             {id: 404, cliente: “José Paulo”, email: “paulo.jose@email.com”},
             {id: 404, cliente: “José Paulo”, email: “paulo.jose@email.com”},
             {id: 404, cliente: “José Paulo”, email: “paulo.jose@email.com”},
             {id: 202, cliente: “Paulo Augusto”, email: “augustos@email.com”},
             {id: 202, cliente: “Paulo Augusto”, email: “augustos@email.com”},
    ]
    function relatorioVendas(arr) {
     return arr.reduce((acc, { id, cliente }) => {
     acc[cliente] = (acc[cliente] || 0) + 1
     return acc
     }, {})
    }
    
    
    console.log(relatorioVendas(compras))
    // Saída:
    { 'Maria Aparecida': 3,
     'Paulo Augusto': 4,
     'Raissa Loureto': 1,
     'José Paulo': 3 }
    

    Para os casos apresentados, o reduce é muito vantajoso.

    No exemplo do faturamento mensal o uso do reduce é extremante eficiente, e se comparar com o uso de forEach() + if().

    No que se trata da frequência de compra pelos clientes o método reduce evita a necessidade de criar objeto auxiliar antes de percorrer os dados.

    Boas Práticas e Armadilhas Comuns ao Usar reduce()🛠️sim

    O método reduce() é poderoso, mas pode ser difícil de entender e manter se não for usado corretamente. Aqui estão algumas boas práticas e armadilhas que você deve evitar ao utilizá-lo.

    A Importância de Inicializar Corretamente o Acumulador

    A inicialização do acumulador é um dos aspectos mais críticos do reduce(). Se ele não for inicializado corretamente, você pode obter resultados inesperados ou até mesmo erros no código.

    ❌Exemplo de erro comum:

    const numeros = [10, 20, 30];
    
    const soma = numeros.reduce((acc, valorAtual) => acc + valorAtual);
    
    console.log(soma); // ERRO se o array estiver vazio
    

    O que está acontecendo aqui?

    Caso o reduce() for chamado sem uma inicialização e o array estiver vazio, ele lança um erro porque não há valor inicial para o acc.

    📌Solução Correta:
    const soma = numeros.reduce((acc, valorAtual) => acc + valorAtual, 0);
    console.log(soma)
    //saída
    // 60
    

    O 0 garante que, mesmo se o array estiver vazio, o código não quebre. Portanto é sempre uma boa prática inicializar o acumulador (acc).

    ✅Dicas para Tornar o Código Mais Legível e Evitar Bugs

    reduce() pode gerar código confuso se não for bem estruturado. Aqui estão algumas dicas para torná-lo mais legível e seguro:

    ✅ Use nomes descritivos para os parâmetros

    Evite nomes genéricos como [a] e [b]. Prefira nomes que indiquem o propósito das variáveis.

    Exemplo ruim:

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

    Exemplo melhor:

    const resultado = valores.reduce((acumulador, valorAtual) => acumulador + valorAtual, 0);
    

    ✅ Evite lógica complexa dentro da função de reduce()

    Se sua função reduce() estiver muito complexa, considere dividi-la em funções auxiliares.

    Condigo difícil de entender:

    const categorias = compras.reduce((acc, { cliente }) => {
    acc[cliente] = acc[cliente] ? acc[cliente] + 1 : 1
    return acc;
    }, {});
    

    Código mais legível com função auxiliar:

    function contarClientes(acc, {cliente}){
     acc[cliente] = (acc[cliente] || 0) + 1
     return acc
    }
    
    const categorias = compras.reduce(contarClientes, {})
    

    Separar a lógica em uma função nomeada melhora a legibilidade e manutenção.

    📌Quando usar reduce() vs map(), filter() e forEach()

    Nem sempre reduce() é a melhor escolha. Veja quando usar cada um dos métodos:

    Método | Quando Usar | Exemplo

    reduce() | Quando você precisa transformar um array em um único valor (número, string, objeto, etc.). | Somar valores, agrupar ítens.

    map() | Quando você deseja transformar cada item do array sem reduzir para um único valor. | Criar um novo array com os preços com desconto.

    filter() | Quando precisa manter apenas alguns elementos do array | Filtrar produtos acima de R$ 50,00.

    forEach() | QUando deseja apenas iterar sobre o array sem criar um novo. | Exibir mensagens no console.

    Exemplo prático comparando reduce(), map(), filter() e forEach()

    const numeros = [1, 2, 3, 4, 5];
    
    // ❌ Exemplo desenecessário de reduce()
    const soma = numeros.reduce((acc, num) => acc + num, 0);
    
    // ✅ Uso correto de map()
    const dobrados = numero.map(num => num * 2); // [2, 4, 6, 8, 10]
    
    //✅ Uso correto de filter()
    const pares = numeros.filter(num => num % 2 === 0); // [2, 4]
    
    // ✅ Uso correto de forEach()
    numero.forEach(num => console.log(num)); // apenas exibe os valores
    

    Aí você deve estar se perguntando - Por que usar o reduce para realizar a soma de itens de um array é um uso desnecessário do reduce? E esta é uma excelente pergunta, afinal fizemos vários exemplos assim neste artigo. A verdade é que usar o reduce para fazer a soma dos itens de um array é como usar uma bazuca para caçar uma formiga, há métodos mais simples que o reduce para realizar esta operação de somar itens de um array como por exemplo:

    const soma = numeros.sum(); // entretanto funciona em algumas versões modernas do JavaScript
    

    Caso não haja suporte para array.sum(), outra abordagem é utilizar o for ou o for-of:

    let soma = 0;
    for (let num of numeros){
    soma += num 
    }
    

    Este formato pode ser mais fácil de entender do que o reduce(), especialmente para iniciantes.

    Quando o reduce() é a melhor escolha?

    Caso estejas lidando com dados mais complexos, onde precisa transformar a estrutura ao mesmo tempo que acumula valores, reduce() se torna extremamente útil.

    Por exemplo, se estivermos somando os valores de objetos dentro de um array:

    const compras = [
     {produto: "Camiseta", preco: 50},
     {produto: "Calça", preco: 100},
     {produto: "Tênis", preco: 200}
    ];
    
    const total = compras.reduce((acc, item) => acc + item.preco, 0);
    
    console.log(total)
    
    //saída
    // 350
    

    Neste caso, reduce() é a melhor escolha por que estamos transformando um array de objetos em um único valor (a soma dos preços).

    Portanto, Quando somamaos um array de números simples é ❌ desnecessário o uso de reduce(), pois há alternativas mais diretas e legíveis. É ✅útil o uso do reduce() quando agregamos dados mais complexos ou precisamos transformar a estrutura ao mesmo tempo.

    O uso do reduce() para somas simples não está errado, necessariamente, mas pode tornar o código menos intuitivo do que outras abordagens 🚀.

    📌Conclusão

    O método reduce() é muito útil para agregar dados, mas pode ser complicado de entender e manter. Assim, sempre inicialize o acumulador corretamente, prefira nomes descritivos para os parâmetros, evite lógicas complexas dentro da função reduce() e use map(), filter() ou forEach() quando forem mais adequados. Deste modo seus códigos serão mais simples, diretos e legíveis. Usando o reduce teus códigos terão um aspecto mais profissional e terá mais fácil manutenção. Portanto, use e abuse do método reduce, mas considerando a moderação.

    Compartilhe
    Recomendados para você
    Microsoft Certification Challenge #3 DP-100
    Decola Tech 2025
    Microsoft AI for Tech - Copilot Studio
    Comentários (1)
    DIO Community
    DIO Community - 21/03/2025 12:32

    Antonio, você fez uma excelente explicação sobre como usar o método reduce() de forma eficiente em JavaScript. Seus exemplos práticos foram muito claros, especialmente ao comparar o uso de reduce() com outros métodos como map(), filter() e forEach(), ajudando a entender quando é realmente necessário usar reduce() e quando outras abordagens são mais simples e legíveis.

    Agora, me conta: qual foi a situação mais desafiadora que você encontrou ao usar reduce() em projetos reais? Houve algum momento em que teve que reestruturar a lógica de reduce() para tornar o código mais eficiente ou legível?

    Recomendados para você