Map, Filter e Reduce

Vamos ver um pouco sobre Array Functions?!

Map, filter e reduce são métodos do JavaScript para manipular arrays. Esses três métodos são os mais importantes para se manipular valores do seu array.

Sem muitas delongas vamos ver como usar esses métodos e entender como eles funcionam !!!

.map()

A função map serve para "varrer" o nosso array modificar alguns valores e devolver um novo array de elementos. A função que manipula esses valores é uma callback, que nós mesmos criamos. Essa função callback precisa modificar e retornar esse valor modificado.

array.map(function(elemento, indice, array){})

Nossa função callback recebe três parâmetros:

  1. Elemento - O Elemento atual do array
  2. Indice - O indice do elemento atual
  3. Array - O Array que chamou a função map

É interessante lembrar que o map retorna um novo array, com a mesma quantidade de elementos que o array original.
Quando usamos o map ?! Um exemplo simples é quando precisamos multiplicar o valor dos elementos do nosso array por 2, por exemplo.

const numeros = [1, 4, 5, 7, 3];

//Vamos multiplicar todos nossos números por 2
const multiplicar = function(numero){
  return numero * 2;
}

const novosNumeros = numeros.map(multiplicar);
console.log(novosNumeros)
// [2, 8, 10, 14, 6]

Simples né ?!

Agora vamos usar o map em um caso um pouco mais complexo, vamos pegar nosso array de produtos e somar o valor de cada item ...

const produtos = [
  { nome: "caneta", qtd: 2, preco: 1.50 },
  { nome: "caderno", qtd: 0, preco: 10.00 },
  { nome: "borracha", qtd: 5, preco: 0.50 },
]

const soma = function(produto){
  const total = produto.qtd * produto.preco;
  return { ...produto, total }
}

const totais = produtos.map(soma)
console.log(totais)
/* 
 [
  { nome: "caneta", qtd: 2, preco: 1.50, total: 3 },
  { nome: "caderno", qtd: 0, preco: 10.00, total: 0 },
  { nome: "borracha", qtd: 5, preco: 0.50, total: 2.5 },
]
*/

.filter()

A função filter, como o próprio nome já diz, serve para filtrar nosso array. Ele retorna um novo array a partir de uma função callback que fará um teste em cada um dos elementos do array, para saber se o elemento fará ou não parte do novo array.

Essa função callback deve retornar um booleano. Caso retorne true, o elemento fará parte do nosso array, caso retorne false, ele não entrará em nosso novo array.

array.filter(function(elemento, indice, array){})

Nossa função callback recebe três parâmetros:

  1. Elemento - O Elemento atual do array
  2. Indice - O indice do elemento atual\
  3. Array - O Array que chamou a função map

Vamos filtrar nossa lista de alunos, e pegar apenas quem tirou nota maior ou igual a 6.

const alunos = [
  { nome: "Raul", nota: 5.99 },
  { nome: "Ana", nota: 7.5 },
  { nome: "Cleber", nota: 1 },
  { nome: "Joana", nota: 10 } 
]

const maiorIgualA6 = function(aluno){
  return aluno.nota >= 6;
}

const passaram = alunos.filter(maiorIgualA6);
console.log(pegaAlunos)
/*
  [
    { nome: "Ana", nota: 7.5 },
    { nome: "Joana", nota: 10 }
  ]
*/

.reduce()

A função reduce funciona de forma diferente você pode modificar os valores do seu array ou agrega-los (somar, dividir etc...).

O grande diferencial é que o reduce pode retornar qualquer coisa(numero, string, array etc...).

Vamos entender melhor como esse cara funciona.

Assim como o map e filter, o reduce consegue manipular o valor de cada elemento do array. Mas o diferencial dele é que ele conta com um acumulador (o valor de todas as iterações até o momento).

Vamos ver melhor como é montado o reduce:

array.reduce(callback, valorInicial);

Calback - Função que será executada em cada elemento do array, ela recebe quatro parâmetros:

  1. acumulador - É o valor acumulado de cada iteração.
  2. valorAtual - O elemento atual do array
  3. indice - O indice do elemento atual do array
  4. array - Array do qual a função reduce foi chamada

ValorInicial - Um valor a ser usado como o primeiro argumento para a primeira chamada do callback. É opcional definir um valor inicial ou não! Caso você não passe nada, o valor inicial do seu acumulador é o primeiro elemento do array.

Você pode encontrar mais detalhes seguindo a documentação oficial.

Vamos tentar entender isso tudo na prática !

Como primeiro exemplo vamos multiplicar os valores de nosso array.

const numeros = [1, 4, 5, 6, 8];

const multiplicador = function(acumulador, elementoAtual){
  return acumulador * elementoAtual;
}

const resultado = numeros.reduce(multiplicador)
console.log(resultado)
// 960

Como vimos acima, nesse exemplo nossa função retornou um número.

Vamos ver como foram cada uma das execuções:

  • Execução 1 – acumulador=1;elementoAtual=4
  • Execução 2 – acumulador=4;elementoAtual=5
  • Execução 3 – acumulador=20;elementoAtual=6
  • Execução 4 – acumulador=120;elementoAtual=8

O resultado final é de 960 !

Vamos a um exemplo usando objetos, o objetivo vai ser calcular a média do valor total de todos os itens

const itens = [
    { nome: "camisa", valor: 32 },
    { nome: "calça", valor: 23 },
    { nome: "chinelo", valor: 16 },
    { nome: "tenis", valor: 7 },
    { nome: "bone", valor: 4 },
    { nome: "bala", valor: 3 },
];

const calculatMediaTotal = function(acumulador, elementoAtual, indice, array){
    if(indice  === array.length - 1) {
        return acumulador / array.length;
    } else {
        return acumulador + elementoAtual.valor;
    }
}

const mediaTotal = itens.reduce(calculatMediaTotal, 0);
console.log(mediaTotal)
//13.666666666666666

Vamos entender o que está acontecendo ...

Eu passei um inicializador com o valor 0, pois como estamos lidando com um objeto, e no return da função estamos retornando apenas um valor numérico não conseguimos acessar acumulador.valor da segunda execução pra frente, o que causaria um erro em nossa aplicação.

A propriedade array é o array que chamou a função reduce. O indice é o indice do elemento do nosso array.

  • Execução 1 – acumulador=0; elementoAtual= { nome: 'camisa', valor: 32 }; indice=0
  • Execução 2 – acumulador=32; elementoAtual= { nome: 'calça', valor: 23 }; indice=1
  • Execução 3 – acumulador=55; elementoAtual= { nome: 'chinelo', valor: 16 }; indice=2
  • Execução 4 – acumulador=71; elementoAtual= { nome: 'tenis', valor: 7 }; indice=3
  • Execução 5 – acumulador=78; elementoAtual= { nome: 'bone', valor: 4 }; indice=4
  • Execução 6 – acumulador=82; elementoAtual= { nome: 'bala', valor: 3 }; indice=5

Após isso dividimos o valor do nosso acumulador pela quantidade de elementos em nosso array(array.length).

Quanto masi praticar o uso do reduce, mais conseguimos entender melhor o funcionamento e quando utilizar o mesmo. Ele, dentre os outros é o mais complicadinho de se usar !!!!

Vamos combinar os tres juntos ?!

Podemos usar os três métodos em conjunto, para ter alguns resultados legais.

const carrinho = [
    { nome: 'caneta', qtde: 10, preco: 7.99 },
    { nome: 'impressora', qtde: 0, preco: 649.50 },
    { nome: 'caderno', qtde: 4, preco: 27.10 },
    { nome: 'lapis', qtde: 3, preco: 5.82 },
    { nome: 'tesoura', qtde: 1, preco: 19.20 }
]

const qtdMaiorQueZero = elemento => elemento.qtde > 0;
const somaTotalCadaItem = elemento => ({ ...elemento, total: elemento.qtde * elemento.preco});
const precoTotal = (acumulador, elementoAtual) => acumulador + elementoAtual.total;

const total = carrinho
    .filter(qtdMaiorQueZero)
    .map(somaTotalCadaItem)
    .reduce(precoTotal, 0)


console.log(total)
//224.96

Aqui eu usei as arrow functions, para conseguir deixar o código mais enxuto.

Vamos entender o que está acontecendo :

  1. Filtramos nosso carrinho, pegando apenas os itens com quantidade maior que 0.
  2. Andamos por cada item do nosso array, retornamos o item com uma propriedade total, que contem o valor total desse item (quantidade * preço)
  3. Somamos o valor total de todos os itens e temos como resultado, o valor do nosso carrinho de 224.96

Bom é isso galera, espero que o post de hoje consiga ajudar a entender melhor essas três funções importantes do JS. Deixe seu feedback construtivo 🤘🏽🤘🏽🤘🏽

Nos vemos na próxima !!!

Comentários