Trabalhando com map, filter e reduce

Entenda os comportamentos e funcionalidades, de forma Prática e direta.

Map

map é um método que executa um callback para cada valor de um array modificando os mesmos, isso faz com que o map crie um novo array com os novos valores obtidos.

Quando utilizar?

Quando você quer que o resultado seja um “array” com “o mesmo” tamanho do “array” inicial, porém com valores modificados (ou não).

Funciona da seguinte maneira:

  • recebe 1 elemento do array.
  • executa a função passada.
    • –adiciona esse elemento no array de resposta.

Aplicação Básica

const array = ['values'];

const arrayResp = array.map(function(value){
	//...Aqui é aplicado o Código de execução que retorna a interação para o arrayResp.
});

console.log(arrayResp);

Exemplo 1: Básico

let list = [1,2,3].map(function(value){
	return value * 2;
});

console.log(list); //[2, 4, 6]
  • Basicamente o método este percorrendo o array e fazendo a multiplicação de cada valor por 2, e a cada soma o resultado é adicionado a variável list, tendo por fim a impressão no console o array [2, 4, 6].

Exemplo 2: Com Arrow Functions

const list = [1,2,3];

let multipliedByTwo = list.map(x => x * 2);

console.log(multipliedByTwo); //[2, 4, 6]
  • Neste exemplo temos o mesmo processo do exemplo anterior, com algumas modificações e a utilização do Arrow functions, desta forma podemos ter um código mais curto (limpo) sem perder a essência.

Exemplo 3: Com Promises

const list = [1,2,3];
let multipliedByTwo = [];

const functionWithPromise = item => {
	return Promise.resolve(item * 2);
}

const anAsyncFunction = async item => {
	return await functionWithPromise(item);
}

const getData = async () => {
	multipliedByTwo.push(
		await Promise.all(
			list.map(item => anAsyncFunction(item))
		)
	);
	return multipliedByTwo[0];
}

async function result(){
	console.log(await getData());
}

result(); // [2 ,4, 6]
  • Agora Observamos um exemplo mais trabalhado, utilizando Promises, simplificando, o map é executado dentro do escopo da Promises.all, neste formato o map é completamente executado e retorna um array com os valor somados, depois é feito o “push” para o variável multipliedByTwo, ou seja, é obtido um array e aplicado dentro do outro, por este motivo o retorno da função getData esta “pegando” o item [0], imprimindo por fim o mesmo resultado dos exemplos anteriores.

NOTA:

O método map não modifica o array original. No entanto, a função callback invocada por ele pode fazê-lo.

Referência: https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Array/map

Filter

Como o nome já diz essa função server para filtrar elementos de um array para um novo. O filter assim como o map, e outros, também é um Functor logo não modificará nosso array original.

Quando utilizar?

Quando você quer que o resultado seja um “array” com o tamanho menor (ou não) que o “array” inicial, porém ”apenas” com valores que passaram por um teste lógico.

Funciona da seguinte maneira:

  • recebe 1 elemento do array.
  • executa a função passada.
    • –caso o retorno seja true.
      • adiciona esse elemento no array de resposta.
    • –caso o retorno seja false.
      • NÃO adiciona esse elemento no array de resposta.

Aplicação Básica

const array = ['values'];

const result = array.filter("//...Aqui é aplicado o Código de execução que retorna o resultado que for 'true' para o result.");

console.log(result);

Exemplos Simples utilizando Arrow Functions:

const list = [1, 5, 9, 8, 2, 10, 3, 4];

let greaterThanFive = list.filter(number => {return number > 5});

console.log(greaterThanFive) //[9, 8, 10]
  • No exemplo acima é aplicado o Arrow functions dentro do escopo do filter retornando apenas os números maiores que 5, criando um novo array na variável greaterThanFive.

Exemplos Simples utilizando Arrow Functions e If ternário:

const list = [1, 5, 9, 8, 2, 10, 3, 4];

let oddNumbers = list.filter(number => (number % 2 == 1 ? true : false));

console.log(oddNumbers) //[1, 5, 9, 3]
  • Neste exemplo junto com o Arrow functions, também esta aplicado o if ternário dentro do mesmo escopo do filter retornando apenas os números ímpares, criando um novo array na variável oddNumbers.

NOTA:

filter não altera o array a partir da qual foi invocado.

Referência: https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Array/filtro

Reduce

Método que executa uma função de redutor (que você fornece) em cada elemento da matriz, resultando em um único valor de saída.

Quando utilizar?

Quando você quer que o resultado seja um “array” (ou qualquer outro tipo existente) e seu(s) o(s) valor(es) pode(m) ser de qualquer tipo.
Ainda pode-se falar que quando precisa iterar o mesmo array usando filter e map, ao invés de fazê-lo duas vezes, o reduce, mesmo sendo mais complexo, é uma opção para isso. Dentro dele dá para em uma interação fazer o que é preciso de um filter e um map.

Funciona da seguinte maneira:

  • A função de redutor usa quatro argumentos: –
    • Acumulador (acc)
    • –Valor Atual (cur)
    • –Índice atual (idx)
    • –Matriz de Origem (src)
  • O valor retornado da sua função redutor é atribuído ao acumulador, cujo valor é lembrado em cada iteração em todo o array e, finalmente, torna-se o valor resultante final único.

Aplicação Básica

const array = ['values'];

const result = array.reduce(function(accumulator, currentValue){
	//... Aqui é aplicado o Código de execução que retorna o resultado para o result.
});

console.log(result);

Exemplos Simples utilizando Arrow Functions:

const list = [1, 2, 3, 4];

const totalSum = list.reduce((accumulator, currentValue) => {
	return accumulator + currentValue;
});

console.log(totalSum); //10
  • No exemplo acima o reduce executa a soma de todas as interações, retornando o valor a soma total na variável totalSum, explicado com mais detalhes no próximo exemplo.
const list = [1, 2, 3, 4];

const reducer = (accumulator, currentValue) => accumulator + currentValue;

console.log(list.reduce(reducer)); //10

console.log(list.reduce(reducer, 5)); //15
  • No exemplo acima foi criada a função reducer, com os parâmetros accumulator & currentValue, onde temos a aplicação da função interna do reduce, desta forma trabalhamos de uma forma mais abrangente.

    1 – Observamos que no primeiro console, passamos apenas como parâmetro a função reducer, isso porque no método reduce o seu primeiro parâmetro é um acumulador, desta forma a primeira interação apenas o acumulador é preenchido, ou seja, no reducer o parâmetro (variável) accumulator, recebe o valor inicial e fica aguardando os demais valores, do segundo em diante, “se existir“, os valores são colocados no parâmetro (variável) currentValue, somando o accumulator com o currentValue , até chegar a ultima interação, por fim imprimindo no console o valor final, neste caso “10”.

    2 – No Segundo Console observamos que diferente do primeiro são passados dois parâmetro no método reduce, como explicado no primeiro console, o método reduce tem como primeiro parâmetro um acumulador, certo, mais se o primeiro é um acumulador, como é que ele trabalha passando 2 parâmetro?, Isto se da por conta de sua estrutura original, na verdade, o reduce recebe valores implícitos, assim como no primeiro console ele recebe a função reducer, que sua estrutura são dois parâmetro, neste caso ele recebe a mesma função, executa por inteiro este primeiro parâmetro “reducer”, que o retorno se torna o acumulador e tem como valor corrente o próximo parâmetro “5”, por fim somando o acumulador com o valor corrente e imprimindo no console o resultado da soma “15”.

NOTA:

Se o valorInicial não tiver sido passado como argumento, então Acumulador
 será igual ao primeiro valor no array e valorAtual será igual ao segundo.

Referência: https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

Atenção:

Todos os Três métodos, map, filter e reduce, só funciona com array, mais existem particularidades que deverão ser “SEMPRE” levadas em considerações.
1 – Garanta “SEMPRE” que será um array que chamará os métodos:

  • Se não for um array, será executado uma exceção de erro que por sua vez quebra todo o processo.

2 – O Array pode ser Vazio?

  • Para o map & filter se o array tiver vazio, os métodos retornarão um array vazio.
  • Para o reduce, se o array tiver vazio, o método executa uma exceção do erro, quebrando todo o processo, desta forma é de suma importância que ao ser utilizado o método reduce, que seja garantido que o array tenha no mínimo um Valor, ou seja, é necessário Sempre testar se o array origem não esta vazio, pois o reduce só funciona se o array origem tiver amenos um valor.

Exemplos Simples para o teste:

let list;
// ou
let list = [];

const result = Array.asArray(list) && list.length > 0 
	? list.reduce((accumulator, currentValue) => accumulator + currentValue)
	: 0
	
console.log(result) //0
  • O teste pode ser feito de várias formas, no exemplo acima, foi propositalmente aplicado um “if ternário” para garantir um valor de retorno, mais podemos apenas criar um “if” padrão executando (no caso do reduce) se for um array e não estiver vazio, para o map & filter não se faz necessário testar se esta vazio, como explicado acima.

Exemplos Utilizando emoji:

fonte: https://google.com.br/imghp

Exemplos Utilizando frutas:

Imagem relacionada
fonte: https://google.com/imghp

Exemplos com a aplicação dos três métodos em conjunto:

const products = [{ id: 1, nome: 'prod 1'},
				{ id: 1, nome: 'prod 1'},
				{ id: 1, nome: 'prod 1'}]
				  
const purchaseRequests = [{ id: 10, idProd: 1, value: 10},
						{ id: 11, idProd: 3, value: 20},
						{ id: 12, idProd: 2, value: 40},
						{ id: 13, idProd: 3, value: 30}]

let arrayResponse = {}

const reducer = (accumulator, currentValue) => accumulator = currentValue

const calculate = (array, value) => {
	array.push(value)
	
	let totalValue = array.reduce(reducer)
	
	let priceAverage = totalValue / array.length
	
	return ([`amount : ${array.length}, priceAverage : ${priceAverage}, totalValue : ${totalValue}`])
}

const result = () => {
	try{
		products.map(value => {
			let values = [];
			(purchaseRequests.filter(request => {
				request.idProd === value.id
					? arrayResponse[request.idProd] = calculate(values,request.value)
					: 0					
				})
			)
		})
		return arrayResponse
	}catch(e){
		return e
	}
}

console.log(result())

/* { '1': ['amount : 1, priceAverage: 10, totalValue : 10'],
	'2': ['amount : 1, priceAverage: 40, totalValue : 40'],
	'3': ['amount : 2, priceAverage: 25, totalValue : 50']} */

Para finalizar deixo o exemplo acima, analise, tire suas próprias conclusões e até o próximo Post!