image

Access unlimited bootcamps and 650+ courses forever

60
%OFF
Article image
Caio Alves
Caio Alves16/08/2023 22:46
Share

Transforme seus arrays com .reduce()

    O javascript conta com diversas funções feitas para auxiliar o programador a resolver problemas que ele possa encontrar no dia a dia, dentre elas existem três que são inspiradas (ou melhor, copiadas) da programação funcional: .map(), .filter() e o nosso foco de hoje, a função .reduce()

    Vamos primeiro com uma definição mais oficial: de acordo com o Mozilla Developer Network (ou MDN):

    “O método reduce() executa uma função reducer (fornecida por você) para cada elemento do array, resultando num único valor de retorno.” - MDN web docs

    Com isso, vemos que o objetivo da função é transformar um array em um único valor, também podemos dizer que estamos reduzindo ele para um valor (entendeu? 'reduziu', 'reduce'...).

    Ok, vamos pegar a sintaxe dele como apresentado no MDN web docs:

    array.reduce(callback( acumulador, valorAtual[, index[, array]] )[, valorInicial])
    

    Podemos ver que ele leva dois parâmetros: uma função callback e um opcional chamado de valorInicial. Vamos começar entendendo o callback: Pela definição, dá pra ver que ele nada mais é do que uma função que será invocada pelo reduce, e ele fará essa invocação passando 4 parâmetros, sendo eles:

    • O acumulador, que será o valor retornado pelas iterações do reduce sobre cada elemento no array.
    • O valorAtual, é basicamente o elemento sendo iterado no array. Por exemplo, se você estiver iterando sobre o array [1, 2], na 1ª iteração, esse parâmetro irá receber o valor 1, (claro, se você definiu um valorInicial também).
    • O index, que é opcional (por isso os colchetes na documentação do MDN), carrega o índice do elemento que está sendo iterado no array. Isso pode ser usado para reduzir o array para um único valor que fica em um índice específico por exemplo.
    • E por fim o array, também opcional, é uma cópia do array que você usou na função .reduce().

    Agora vamos a um exemplo mais prático. Estou usando uma parte da resposta da PókeAPI, que traz diversas informações sobre Pókemons, e quero reduzir o array de habilidades para uma string com o nome das habilidades que o pókemon possui, mas com um porém: a habilidade precisa ter o atributo is_hidden como falso.

    const pokeapi_response = {
    abilities: [
      {
        ability: {
          name: "blaze",
          url: "https://pokeapi.co/api/v2/ability/66/",
        },
        is_hidden: false,
        slot: 1,
      },
      {
        ability: {
          name: "solar-power",
          url: "https://pokeapi.co/api/v2/ability/94/",
        },
        is_hidden: true,
        slot: 3,
      },
    ],
    base_experience: 62,
    name: "charmander",
    order: 5,
    past_types: [],
    id: 4,
    species: {
      name: "charmander",
      url: "https://pokeapi.co/api/v2/pokemon-species/4/",
    },
    };
    const ability_string = pokeapi_response.abilities.reduce(function (acumulador, valorAtual) {
    const ability = valorAtual.ability;
    if (valorAtual.is_hidden == false) {
      if(acumulador == '') acumulador = ability.name;
      else acumulador += `, ${ability.name}`;
    }
    return acumulador;
    }, "");
    console.log(ability_string);
    

    Se você executar este código, verá que ability_string retorna uma string com o nome de todas as habilidades que o charmander possui e que não tem is_hidden como false. Recomendo você copiar este código e manipular para conseguir entender melhor como que a função funciona. Se você fez isso e começou a aparecer no console algo como `[object Object], solar-power`, meus parabéns você acaba de descobrir uma das funções do último parâmetro que o reduce possui: o valorInicial.

    Vamos primeiro fazer uma breve definição: O valorInicial define qual será o valor do acumulador na sua 1ª iteração. Vamos a um exemplo simples e direto:

    [1, 2, 3].reduce((acumulador, valorAtual) => {
    console.log(acumulador); // 7, 8, 10
    return acumulador + valorAtual;
    }, 7); // O valor retornado é 13
    

    Vamos focar apenas no retorno do console.log. Eu escrevi no comentário as saídas que aconteceram e, como pode ver, temos o valor 7 sendo o valor do acumulador na 1ª vez que a função é chamada.

    Mas por quê isso é interessante? Vamos responder com uma outra pergunta: O que acontece quando você não define este parâmetro?

    A resposta é muito simples e está na documentação do MDN sobre o valorInicial:

    "Opcional. Valor a ser usado como o primeiro argumento da primeira chamada da função callback. Se nenhum valorInicial é fornecido, o primeiro elemento do array será usado como o valor inicial do acumulador e o valorAtual não será lido. Chamar reduce() em uma array vazia sem valor inicial retornará um erro." - MDN web docs.

    Como podemos ver, quando ele não é definido, o valorInicial passa a ser o 1º elemento do array (efetivamente o elemento que possui o índice 0), e se lembrarmos bem, no nosso "pókexemplo" nós tinhámos um array de objetos, como estamos fazendo uma concatenação de strings com um objeto, ele acaba se tornando [object Object], solar-power, pois o valor contido no acumulador é um objeto mesmo.

    Outro ponto que merece atenção é o trecho final da definição de valorInicial: "Chamar .reduce() em uma array vazia sem valor inicial retornará um erro". Visto que não é incomum o .reduce() trabalhar junto com o .filter(), existe a possibilidade dele retornar um array vazio quer será usado no reduce, neste caso, definir um valorInicial pode te poupar alguns minutos de busca no StackOverflow (ou no ChatGPT).

    Pronto! Agora você têm uma boa noção do que a função .reduce() pode fazer e eu espero de verdade que tenha sido interessante este conteúdo que preparei. Me diga nos comentários o que achou deste artigo e se você quer mais conteúdos explicados dessa forma.

    Enfim, isso é tudo. Até a próxima!

    Share
    Comments (0)