Hamburger Icon
JavaScript Reduce: ejemplos prácticos para el día a día

JavaScript Reduce: ejemplos prácticos para el día a día

El método reduce de JavaScript es uno de los más versátiles que podemos encontrar. Aquí verás unos cuantos ejemplos.

Este post da por supuesto el funcionamiento básico del método reduce, si no lo tienes muy claro puedes consultar este otro artículo donde te explicaba cómo y cuándo usarlo.

Básicamente, reduce te permite aplicar una función sobre todos los elementos de un array almacenando un valor acumulado que será el resultado final.

Sumar los números en un array

Empezamos por lo más básico. Verás este ejemplo en muchos otros artículos, pero va muy bien para empezar a ver el potencial de reduce.

const numeros = [1, 2, 3, 4, 5]
const reductor = (acumulado, num) => acumulado + num

const suma = numeros.reduce(reductor)

console.log(suma) // 15

Tenemos un array de números y una función reductora. La función reductora recibe dos parámetros (el acumulado y el valor a sumar) y devuelve la suma de los mismos.

Cuando aplicamos el método reduce sobre el array pasándole la función reductora, el valor inicial será el primer elemento del array, este es el comportamiento por defecto cuando no indiquemos otra cosa. En otras palabras, el primer elemento del array será el valor inicial de la variable acumuladora.

El método reduce aplicará la función reductora sobre cada elemento del array y ésta, al mismo tiempo, guardará el acumulado en cada iteración, devolviendo este acumulado cuando termine.

Sumar valores en un array de objetos

El ejemplo anterior es una forma sencilla de ver cómo usar reduce, pero en la práctica si quieres sumar los valores en un array de números seguramente no te vas a liar haciendo un reduce.

Vamos a ver un ejemplo más realista para empezar a ver el potencial real de reduce. Queremos sumar tanto la cantidad de artículos como el precio total que tenemos en una lista de la compra:

const listaCompra = [
  { producto: "iogur", cantidad: 4, precio: 2 },
  { producto: "jamón", cantidad: 1, precio: 6 },
  { producto: "nachos", cantidad: 1, precio: 3 },
  { producto: "café", cantidad: 2, precio: 4 },
]

const reductor = (acumulado, num) => acumulado + num

const totalProductos = listaCompra.map((item) => item.cantidad).reduce(reductor)

const totalPrecio = listaCompra.map((item) => item.precio).reduce(reductor)

console.log(totalProductos) // 8
console.log(totalPrecio) // 15

Veamos qué está sucediendo aquí paso a paso. Primero hemos definido la lista de la compra, que consiste en un array de objetos, donde cada objeto contiene el nombre del producto, una cantidad y un precio total.

Definimos la función reductora, que es igual que en el ejemplo anterior, una simple suma, porque eso es lo que queremos hacer, acumular sumas (de unidades y de precio).

Entonces, para calcular tanto el total de productos como el total del precio, primero llamaremos a la función map que nos devolverá, respectivamente, un listado de las unidades y de los precios.

Sobre ese array que nos devuelve map ya aplicamos reduce igual que en el ejemplo anterior, para calcular el acumulado que nos interesa.

Si quieres practicar, sobre este ejemplo imagina que el precio indicado en cada item es un precio unitario, no total. El precio total de cada item será la multiplicación del precio unitario por las unidades. En base a eso, puedes pensar la función reductora.

Encontrar máximos y mínimos

Si pensabas que reduce se reducía (chistaco) a sumar valores, pues te voy a demostrar que no.

Si quieres encontrar, por ejemplo, la fecha más antigua en un array, podemos hacer algo así:

const fechas = [
  "1991/05/17",
  "1991/06/24",
  "2009/08/17",
  "1850/01/15",
  "1950/03/21",
]

const reductor = (masAntigua, fecha) => {
  if (masAntigua < fecha) {
    return masAntigua
  }
  return fecha
}

const fechaMenor = fechas.map((fecha) => new Date(fecha)).reduce(reductor)
console.log(fechaMenor) // Tue Jan 15 1850 00:00:00

Vemos que tenemos un listado de fechas en formato string. La función reductora recibe como parámetros el acumulador y una fecha. En este caso el acumulador es simplemente la fecha más antigua encontrada hasta el momento. Se devuelve la fecha menor de las dos.

Igual que antes, primero usamos el método map para transformar la fecha a un formato adecuado y sobre el array resultante se aplica el método reduce.

Tampoco pasamos un valor inicial, ya que la primera fecha será usada como tal.

Quitar duplicados en un array

Seguro que en alguna ocasión has tenido un array de elementos con algunos repetidos. Hay muchas formas de quitar los duplicados, pero una es aplicando reduce:

const conDuplicados = ["a", "b", "c", 1, 2, 3, "a", 2, "d", 4]

const reductor = (noRepetidos, valor) => {
  if (noRepetidos.indexOf(valor) === -1) {
    noRepetidos.push(valor)
  }
  return noRepetidos
}

const sinDuplicados = conDuplicados.reduce(reductor, [])

console.log(sinDuplicados) // ["a", "b", "c", 1, 2, 3, "d", 4]

En esta ocasion, el acumulador de la función reductora es el array de elementos sin repetidos. Si el elemento actual no se encuentra dentro, lo metemos, luego devolvemos el acumulador.

Cuando llamamos al método reduce, a parte de indicar la función reductora, pasamos un array vacío que hará de valor inicial.

Intersección de elementos de un array

Al contrario que en el ejemplo anterior, en vez de quitar duplicados, nos queremos quedar con los elementos repetidos en varios arrays:

const array1 = [1, 2, 3, "b", 4, 5]
const array2 = ["a", "b", "c", "d", 3]
const array3 = [array1, array2]

const reductor = (comunes, listado) =>
  comunes.filter((item) => listado.includes(item))

const interseccion = array3.reduce(reductor)

console.log(interseccion) // [3, "b"]

En esa ocasión, la función reductora recibe un array de elementos y devuelve otro array filtrando y dejando solo los elementos que coinciden con el listado que se le pasa.

Como valor inicial de nuevo se usará el primer elemento del listado de arrays que usaremos, por eso no indicamos ninguno.

Conclusiones

El método reduce es un comodín que nos permite hacer de todo. Nos facilita mucho el recorrido y tratamiento de arrays, consiguiendo su mayor potencial cuando se combina con otros métodos como map o filter.

Con estos ejemplos deberías poder aplicar reduce en situaciones triviales. Aunque parezca confuso al principio, con reduce podemos resolver de forma elegante una cantidad bastante grande de casos de uso gracias a su versatilidad.

Siempre que necesites recorrer arrays y generar un resultado acumulado, reduce va a ser tu mejor aliado. Usando map podrás transformar los elementos antes de aplicar reduce, mientras que con filter o find podrás filtrar y buscar elementos concretos sobre los que te interesa usar tu función reductora.