Manipular arrays es uno de los trabajos más repetitivos que realizamos al trabajar con JavaScript. Y hay tres métodos muy conocidos que nos ayudan en esta manipulación: map(), filter() y reduce(). Son métodos conocidos, pero no siempre recordamos el objetivo de cada uno de ellos.
En este artículo hablaremos sobre las diferencias entre esos métodos y en qué situaciones pueden ayudarnos.
Estos métodos poseen una sintaxis más concisa y legible y nos permiten realizar en pocas líneas lo que necesitaríamos hacer con otros métodos de bucle, como el método forEach(), por ejemplo. ¡Veamos ahora la definición de estos métodos!
map() - Ejecuta una función en todos los elementos de un array
El método map() tiene el objetivo de ejecutar una función en cada elemento de un array. Esta afirmación quizás nos haga preguntar: “¿Pero no es eso lo que hace el forEach()?” Realmente, el forEach() también manipula los datos de un array. Sin embargo, hay una diferencia.
El método map() devuelve un nuevo array tras la manipulación, es decir, no sobrescribe el array original. En realidad, todos los métodos que aprenderemos en este artículo devuelven un nuevo array como respuesta.
Además, el método map() tiene un mejor rendimiento que el forEach(). Veamos un ejemplo en el que usar el map() nos permite realizar un cambio en los datos de manera muy sencilla.
Imagina que tenemos una lista de productos siendo mostrados en nuestra página y deseamos agregar un descuento del 10% en el precio de esos productos. ¿Cómo podríamos hacer esto con el map()? Podríamos tener un array de precios, como el siguiente:
const productsPrices = [100, 150, 300];
Entonces, podríamos llamar al método map() y almacenar su retorno en una nueva variable, llamada productsDiscount, de esta forma:
const productsDiscount = productsPrices.map(price => {
return price * 0.9;
});
Ten en cuenta que es necesario definir un return en el método para que funcione. Sin el return el nuevo array tendría todos sus valores como undefined.
Como nuestro método solo devolvió el valor del precio, podríamos simplificar aún más este código, definiéndolo en una sola línea:
const productsDiscount = productsPrices.map(price => price * 0.9);
Ahora, si definimos un console.log() en la variable antigua y en la nueva, veremos el siguiente resultado:
¡Excelente! El array antiguo sigue sin cambios, pero el nuevo tiene los descuentos definidos correctamente.
En este ejemplo usamos un array de precios, pero ¿cómo podríamos hacer esto con un objeto? Imagina que ahora tenemos un array de objetos, que almacena la información de nuestros productos:
const products = [{
name: 'TV',
price: 100
}, {
name: 'Monitor',
price: 150
}, {
name: 'SSD',
price: 300
}];
¿Cómo podríamos aplicar los mismos 10% de descuento en este caso? Una solución es usar el método Object.keys() para encontrar los índices de nuestro array de productos y ejecutar el map() en esos índices. Así, podemos alterar la clave del objeto de productos en cada uno de sus índices. Nuestro código quedaría así:
const productsDiscount = Object.keys(products).map(key => products[key]['price'] *= 0.9);
¡De esta forma seguiría funcionando!
filter() - Filtra un array
El siguiente método del que hablaremos es el filter(). Como su propio nombre indica, tiene el objetivo de filtrar la información de un array. Su funcionalidad consiste en que le damos una condición. Él aplicará esta condición a todos los elementos de nuestro array y aquellos que se ajusten a la condición serán devueltos y añadidos al nuevo array de salida. De esta forma, a diferencia de lo que ocurre en map() y reduce(), el filter() siempre devolverá true o false.
Quizás nos preguntemos: “¿En qué situaciones necesitaría filtrar un array?”. Es común hacer esto cuando estamos eliminando un elemento de un array o filtrando los resultados de un array de datos.
Creemos un ejemplo de eliminación de un registro. Imagina que tenemos un array de usuarios, con la siguiente estructura:
const users = [1, 2, 3, 4];
Acabamos de eliminar al usuario con id igual a 2 y deseamos quitarlo de la página. Si estuviéramos usando algún framework de JavaScript, como React, Angular o Vue, podríamos actualizar los datos de la página sin necesidad de refrescarla. Podríamos usar este código:
const newUsers = users.filter(user => user !== 2);
El array newUsers contendrá todos los usuarios que tienen id diferente de 2. Si ejecutamos un console.log() en las dos variables, veremos el siguiente resultado:
Nota que el nuevo array no contiene al usuario 2, exactamente lo que deseábamos ?
reduce() - Reduce un array en un único resultado
El método reduce() es muy interesante y puede ser utilizado cuando deseamos realizar alguna sumatoria o cuando deseamos fusionar varios arrays en uno solo. Reduce todos los valores de un array en un único resultado, basándose en la función que le proporcionamos.
Los dos primeros parámetros de este método son muy importantes. El primero representa el resultado final de la reducción del array. Este valor es incrementado a lo largo del proceso del reduce(), a cada vuelta de este bucle. El segundo parámetro involucra el valor de cada índice del array. Veamos un ejemplo para que este concepto quede más claro para nosotros. ?
Imagina que poseemos una variable que contiene la información de la facturación semestral de una empresa. Este array tiene la siguiente estructura:
const annualBilling = [1500, 1800, 700, 5000, 1600, 18000];
Ahora imagina que deseamos saber cuál fue el valor total de la facturación en este período. Necesitaríamos realizar la suma de cada uno de los valores de este array. El método reduce() podría ayudarnos. Para ello, bastaría con sumar el valor total previo en cada vuelta de la repetición con el valor actual de la facturación en cada vuelta. Nuestro código quedaría así:
const totalBilling = annualBilling.reduce((total, currentValue) => {
return total + currentValue;
}, 0);
Cuando ejecutemos un console.log() en la variable totalBilling, veremos el siguiente resultado:
¡Muy bien! La suma se realizó con éxito. Nota que el segundo parámetro informado para el reduce() fue el número 0. Este parámetro representa a partir de qué número deseamos iniciar nuestra operación de suma. Por defecto este valor es 0. Así, no necesitaríamos informarlo en este caso, si no lo deseáramos.
Usando todos los métodos juntos
Estos tres métodos son realmente increíbles. Pero, si ya son increíbles por sí solos, ¡imagina si pudiéramos usar los tres juntos! ¡Eso es completamente posible! Como cada uno de esos métodos devuelve un nuevo array, podemos luego llamar a otro método, realizando lo que podríamos llamar un “encadenamiento de métodos de array”.
Imagina que poseemos un array que almacena a los empleados de nuestra empresa. Este array tiene la siguiente estructura:
const employees = [{
name: 'Luke',
department: 'Finanzas',
salary: 1500
}, {
name: 'Han',
department: 'Finanzas',
salary: 1200
}, {
name: 'Ben',
department: 'Marketing',
salary: 2000
}, {
name: 'Leia',
department: 'Marketing',
salary: 1750
}, {
name: 'Rey',
department: 'Finanzas',
salary: 1000
}]
Deseamos saber cuánto recibiría en total el Departamento de Finanzas si les diéramos un aumento del 50%. Para saber esta información, necesitaríamos: 1) filtrar del array quiénes son los empleados del Departamento de Finanzas, 2) agregar un 50% de aumento en sus salarios y 3) realizar la suma total de esos salarios. Podríamos hacer esto usando los métodos que aprendimos en este artículo. Nuestro código quedaría así:
const totalSalary = employees.filter(employee => {
return (employee.department === 'Finanzas');
}).map(item => {
return item.salary *= 1.5;
}).reduce((total, currentValue) => {
return total + currentValue;
});
Al ejecutar un console.log() en la variable totalSalary, el siguiente resultado sería devuelto:
¡Excelente! Descubrimos el valor total de esta operación.
Usamos arriba la forma “extensa”, definiendo el return en cada uno de los métodos. Sin embargo, como ya hemos visto en este artículo, podemos simplificar este código, dejándolo de la siguiente manera:
const totalSalary = employees
.filter(employee => (employee.department === 'Finanzas'))
.map(item => item.salary *= 1.5)
.reduce((total, currentValue) => total + currentValue);
¡Ahora sí, mucho mejor!
Conclusión
En este artículo vimos la diferencia entre los métodos map(), filter() y reduce(). Aprendimos incluso cómo usar estos tres métodos en conjunto para una manipulación de arrays mucho más simple y práctica.
Puedes aprender mucho más sobre arrays y otros conceptos fundamentales de JavaScript a través de nuestro Curso Completo de JavaScript, donde enseñamos los varios conceptos de este increíble lenguaje a través de proyectos sensacionales.
¡Hasta el próximo artículo :)