Aprende a usar reduce en JavaScript

En este taller te explico el funcionamiento del método Array.reduce. Se trata de una operación transformadora de reducción, lo que significa que convierte los elementos de un array (transformación), pero se diferencia de un map en que un reduce genera un único elemento, no otro array de elementos. ¿Estás aprendiendo a programar? Reduce puede sonar inicialmente complicada de utilizar debido a que tiene una interfaz de uso un poco extraña y a que hace unas transformaciones que son complicadas de imaginar en nuestra cabeza, pero mi objetivo en este taller es que puedas comprender de forma visual y con ejemplos prácticos cómo usar reduce en JavaScript mediante ejemplos fáciles de seguir, por ejemplo, cómo organizar los elementos de un array por categoría, o cómo transformar los elementos de un array en una suma. Un taller esencial que puede apoyar lo que estés aprendiendo sobre desarrollo web por tu cuenta, en la universidad, escuela o bootcamp, y que te permitirá escribir mejor código.

Reduce es una función que a menudo nos resulta intimidante al principio, pero en realidad su esencia es bastante sencilla y poderosa. En JavaScript, Reduce nos permite transformar un array en un único valor, que puede ser un número, un objeto, otro array o cualquier tipo de dato. Esto lo diferencia de funciones como map, que transforman un array en otro array con el mismo número de elementos, aplicando una operación a cada uno de ellos.

Para entender mejor cómo funciona Reduce, pensemos en un array de letras, por ejemplo ['A', 'B', 'C', 'D']. Mientras que map nos devolvería otro array con la misma cantidad de elementos transformados, Reduce nos permite condensar todo ese array en un solo valor. Por ejemplo, podríamos sumar el total de caracteres de todas las palabras en un array, o agrupar tareas según su prioridad en un objeto.

Un caso común de uso es sumar los precios de un carrito de compras representado como un array de números. Reduce nos permite iterar sobre cada elemento y acumular la suma total, devolviendo un único número que representa el total. Otro ejemplo más complejo es agrupar tareas por prioridad en un objeto, donde cada clave representa una prioridad y su valor es un array con las tareas correspondientes.

El funcionamiento de Reduce se basa en dos parámetros principales: un callback y un valor inicial para el acumulador. El callback es una función que se ejecuta una vez por cada elemento del array, recibiendo como parámetros el acumulador y el elemento actual. El acumulador es una variable que se va actualizando en cada iteración con el resultado parcial, y que finalmente se devuelve como resultado total de la operación.

Veamos un ejemplo sencillo para contar el total de letras en un array de palabras:

const flores = ['Margarita', 'Amapola', 'Petunia', 'Geranio'];

const totalLetras = flores.reduce((acumulador, item) => {
  console.log('Acumulador:', acumulador, 'Item:', item);
  return acumulador + item.length;
}, 0);

console.log('Total de letras:', totalLetras);

En este código, el acumulador comienza en 0. En cada iteración, sumamos la longitud de la palabra actual al acumulador. Así, después de procesar todas las palabras, obtenemos el total de letras. Durante la ejecución, podemos observar cómo el acumulador va aumentando con cada palabra.

Otro ejemplo más avanzado es agrupar tareas por prioridad. Supongamos que tenemos un array de objetos donde cada objeto representa una tarea con una propiedad prioridad que puede ser 'A', 'B' o 'C'. Queremos transformar este array en un objeto que tenga como claves las prioridades y como valores arrays con las tareas correspondientes.

Podemos hacerlo así:

const tareas = [
  { nombre: 'Tarea 1', prioridad: 'A' },
  { nombre: 'Tarea 2', prioridad: 'B' },
  { nombre: 'Tarea 3', prioridad: 'A' },
  { nombre: 'Tarea 4', prioridad: 'C' },
  { nombre: 'Tarea 5', prioridad: 'B' }
];

const tareasPorPrioridad = tareas.reduce((objeto, tarea) => {
  if (!objeto[tarea.prioridad]) {
    objeto[tarea.prioridad] = [];
  }
  objeto[tarea.prioridad].push(tarea);
  return objeto;
}, {});

console.log(tareasPorPrioridad);

Aquí, el acumulador es un objeto vacío que vamos llenando con arrays para cada prioridad. En cada iteración, comprobamos si la prioridad de la tarea ya existe como clave en el objeto; si no, la inicializamos con un array vacío. Luego, añadimos la tarea al array correspondiente. Al final, obtenemos un objeto que agrupa las tareas según su prioridad.

Es importante tener en cuenta que aunque Reduce es muy flexible y potente, no siempre es la mejor opción para todas las situaciones. A veces, usar funciones específicas como sum o métodos más claros puede hacer que nuestro código sea más legible y fácil de mantener. Reduce puede llevar a escribir código complicado si no se usa con cuidado.

En resumen, Reduce nos permite acumular resultados parciales a lo largo de un array para obtener un único valor final. Su callback recibe el acumulador y el elemento actual, y debe devolver el nuevo valor del acumulador para la siguiente iteración. El valor inicial del acumulador es fundamental para definir el tipo de resultado que queremos construir, ya sea un número, un objeto o cualquier otro tipo.

Con estos conceptos claros y algunos ejemplos prácticos, podemos empezar a integrar Reduce en nuestros desarrollos con confianza y aprovechar su potencial para transformar arrays en valores únicos de forma eficiente y elegante.

Lista de reproducción
  1. 1
    forEach vs map
    13 minutos
  2. 2
    El tutorial definitivo de promesas
    33 minutos
  3. 3
    Aprende a usar reduce en JavaScript
    21 minutos
  4. 4
    Cómo crear tests en NodeJS 20 sin instalar dependencias
    10 minutos
  5. 5
    Primeros pasos con AlpineJS, el microframework mágico
    9 minutos