map, filter y reduce en JavaScript: tres formas de recorrer un array

En esta página
Enterate del próximo post
Un mail cuando publico algo nuevo. Sin spam y te podés dar de baja cuando quieras.

Un mail cuando publico algo nuevo. Sin spam y te podés dar de baja cuando quieras.
El post anterior sobre arrays mostró cómo crear uno, leer un elemento por su posición y consultar cuántos tiene. Para transformarlo, filtrarlo o resumirlo en un solo valor no hace falta escribir ese recorrido a mano: map, filter y reduce son funciones de orden superior (cada una recibe otra función como argumento, la misma idea del post anterior a arrays) que ya resuelven el recorrido por dentro.
const precios = [100, 200, 300];
const conIva = precios.map((precio) => precio * 1.21);
console.log(conIva);
// [ 121, 242, 363 ]map recibe una función, la aplica a cada elemento del array original y devuelve un array nuevo con el resultado de cada aplicación, en el mismo orden y con el mismo largo que el original. precios no cambia: map no lo modifica, arma uno distinto.
const precios = [100, 200, 300];
const etiquetas = precios.map((precio) => `$${precio}`);
console.log(etiquetas);
// [ '$100', '$200', '$300' ]
console.log(precios);
// [ 100, 200, 300 ]La función que recibe map puede devolver cualquier tipo de valor, no solo una versión transformada del mismo tipo: acá cada elemento pasa de número a string. precios sigue intacto después de las dos llamadas a map de este post: ninguna de las dos lo tocó.
console.log(10 > 5);
// true
console.log(3 > 5);
// false> compara dos valores y da como resultado uno de dos valores posibles, true o false, según si la comparación es cierta o no. Ese resultado es exactamente lo que necesita filter para decidir qué elementos conservar.
const precios = [100, 200, 300];
const caros = precios.filter((precio) => precio > 150);
console.log(caros);
// [ 200, 300 ]filter recibe una función que, para cada elemento, devuelve true o false. Se queda solo con los elementos donde esa función dio true, y arma con ellos un array nuevo: más corto que el original, o del mismo largo si todos calificaron.
const precios = [100, 200, 300];
const carisimos = precios.filter((precio) => precio > 1000);
console.log(carisimos);
// []
console.log(carisimos.length);
// 0Si ningún elemento cumple la condición, filter no da ningún error: devuelve un array vacío, la misma estructura ya vista en el post de arrays, solo que llegada por descarte en vez de escrita a mano.
const precios = [100, 200, 300];
const total = precios.reduce((acumulador, precio) => acumulador + precio, 0);
console.log(total);
// 600reduce recibe dos argumentos: una función y un valor inicial. La función recibe dos parámetros en cada paso, el acumulador (lo que se llevaba acumulado hasta el momento) y el elemento actual, y devuelve el nuevo acumulador. El valor inicial (acá 0) es lo que arranca el acumulador antes de procesar el primer elemento. A diferencia de map y filter, reduce no devuelve un array: devuelve un único valor, el resultado final del acumulador después de recorrer todo el array.
const palabras = ["Hola", "mundo", "de", "JavaScript"];
const frase = palabras.reduce((acumulador, palabra) => `${acumulador} ${palabra}`);
console.log(frase);
// Hola mundo de JavaScriptEl valor inicial es opcional. Si no se pasa, reduce toma el primer elemento del array ("Hola") como acumulador inicial y arranca desde el segundo ("mundo"), en vez de desde el índice 0. Sirve para casos como este, donde el primer elemento ya es del mismo tipo que el resultado final y no hace falta un punto de partida aparte.
const precios = [100, 200, 300, 50];
const total = precios
.filter((precio) => precio > 150)
.map((precio) => precio * 0.9)
.reduce((acumulador, precio) => acumulador + precio, 0);
console.log(total);
// 450filter y map devuelven un array, así que el resultado de uno puede encadenarse directo con el siguiente sin variables intermedias: filter se queda con los precios mayores a 150 (200 y 300), map les aplica un descuento del 10% (180 y 270), y reduce los suma en un único total (450). Cada método hace una sola cosa; encadenarlos es lo que arma el recorrido completo, un paso por vez.
maptransforma cada elemento de un array y devuelve uno nuevo del mismo largo.filterse queda solo con los elementos donde una función devuelvetrue, y devuelve un array nuevo, del mismo largo o más corto.reducerecorre el array acumulando un único valor, a partir de una función y un valor inicial opcional. Los tres reciben una función como argumento en vez de mutar el array original, y por eso se pueden encadenar uno después de otro.
El próximo post trata la recursión: una función que se llama a sí misma, y cómo esa práctica hace crecer la pila de llamadas que ya se explicó en el post de Call Stack.