Reduce: acumular y transformar arrays en JavaScript

Clase 11 de 24Curso de Manipulación Avanzada de Datos con JavaScript

Resumen

Domina reduce en JavaScript con ejemplos claros y conectados a programación funcional. Aquí verás por qué es más flexible que map y filter, cómo usar el accumulator y el init value, y cómo crear pipelines de transformación elegantes para sumar, promediar y resolver retos de algoritmia.

¿Por qué reduce en JavaScript es más poderoso que map y filter?

Reduce puede replicar lo que hace map y lo que hace filter, y además ir más allá. Transforma un array en una mínima expresión según tu lógica de negocio: un número, un objeto, un array nuevo o incluso una estructura más grande.

  • map: transforma cada elemento y conserva la longitud. Crea un nuevo estado.
  • filter: selecciona elementos que cumplan una condición. La longitud nunca aumenta.
  • reduce: rompe la regla de longitud fija. Totaliza, minimiza o maximiza según la lógica. Devuelve un único valor o cualquier estructura que definas.
  • Programación imperativa vs. programación funcional: si ya tienes pipelines de transformación, reduce es ideal para expresar la intención sin bucles explícitos.

Consejos clave:

  • Define siempre un estado inicial (init value): número, objeto o array, según el resultado esperado.
  • Piensa en el proceso como acumulación paso a paso: el valor anterior + el actual devuelve el nuevo estado.

¿Cómo funciona el accumulator y el estado inicial en reduce?

Reduce itera el array y va acumulando un resultado. La primera iteración usa el init value como accumulator. La función siempre debe retornar el nuevo estado.

¿Qué parámetros recibe reduce?

  • accumulator: el valor acumulado hasta el momento.
  • current value: el elemento actual del array.
  • current index: la posición actual.
  • array: la referencia completa al array original.

Ejemplo didáctico: suma total con reduce.

const numbers = [1, 2, 3, 4, 5]; const sum = numbers.reduce((accumulator, currentValue, currentIndex, array) => { // acumula el resultado sumando el valor actual return accumulator + currentValue; }, 0); // init value console.log(sum); // 15

Puntos importantes:

  • Siempre retorna en el callback function.
  • El accumulator de la primera vuelta es el init value.
  • El resultado final es el último valor retornado por el callback function.

¿Por qué definir un init value explícito?

  • Evita comportamientos inesperados en arrays vacíos.
  • Te permite reducir hacia cualquier estructura: número, objeto o array.
  • Hace explícita la intención del algoritmo.

¿Cómo calcular promedio y encadenar pipelines con map y reduce?

Un patrón común es extraer datos con map y totalizar con reduce. Luego divides entre la longitud para obtener el average.

const customers = [ { name: 'Ana', age: 20, hobbies: ['leer'] }, { name: 'Luis', age: 21, hobbies: ['música'] }, { name: 'Mia', age: 22, hobbies: ['cine'] }, ]; const averageAge = customers .map(c => c.age) // [20, 21, 22] .reduce((acc, n) => acc + n, 0) // totaliza edades / customers.length; // promedio console.log(averageAge);

Beneficios del pipeline:

  • Código declarativo y legible.
  • Compones pasos: mapfilterreduce → paso siguiente.
  • Encapsulas la lógica de negocio sin bucles repetitivos.

¿Cómo resolver la suma máxima de consecutivos con reduce?

Reto propuesto: encontrar la suma más alta de dos números consecutivos en un array, incluso con negativos o desordenado.

Idea: en cada paso, suma el elemento actual con el anterior y guarda el máximo visto.

const numbers = [3, 4, 2, 5, 1, -2]; const maxPairSum = numbers.reduce((acc, curr, index, array) => { if (index === 0) return acc; // no hay par para el primero const pairSum = array[index - 1] + curr; return Math.max(acc, pairSum); }, -Infinity); // init value para máximos console.log(maxPairSum); // 9 en un caso como [4, 5, ...]

Claves del patrón:

  • Usa el current index para acceder al vecino anterior.
  • Define un init value adecuado: para máximos, algo muy pequeño.
  • Retorna siempre el mejor estado conocido.

¿Quieres que revisemos un caso real con tus datos o que comentemos optimizaciones de tu pipeline actual?