Javascript
Programación funcional
reduce()

Método Javascript reduce(): array index, valor inicial, object, sum async, break

El método Array.prototype.reduce() en JavaScript es uno de los métodos de array más utilizados, Es un buen ejemplo de la programación funcional de JavaScript.

Cuando aprendes a programar por primera vez, eres introducido a la programación procedimental y orientada a objetos, El método reduce() no siempre es fácil de entender intuitivamente. Así que, en este post, voy a echar un vistazo desde la programación funcional hasta varios ejemplos del mundo real para entender el método reduce().

1. Programación Funcional JavaScript en pocas palabras

La programación funcional es un paradigma de programación que se refiere a una técnica para diseñar el comportamiento de un programa basado en funciones en el sentido matemático.

En la programación funcional, mientras pongas los mismos valores en una función, siempre deberías obtener el mismo resultado. Una función que sigue este principio se llama función pura y no debería cambiar ningún valor de estado en su comportamiento. Si lo hace, se llama efecto secundario, y la programación funcional pretende minimizarlos.

También enfatiza la inmutabilidad del estado y los datos, así que en lugar de cambiar los valores de una estructura de datos diseñamos nuestros programas para crear nuevas estructuras de datos. Esto significa que si quieres cambiar el array [1, 2, 3] a [1, 2, 4], creas un nuevo array [1, 2, 4]. Los programas diseñados de esta forma tienen grandes ventajas para cosas como la programación concurrente, en la que se accede a los datos simultáneamente.

Por último, JavaScript trata a las funciones como ciudadanos de primera clase - objetos que se pueden utilizar en cualquier lugar: variables, parámetros, valores de retorno, etc, Es un lenguaje ideal para la programación funcional. Como resultado, muchos desarrolladores de JS utilizan la programación funcional para escribir código mantenible y fiable.

Las funciones que se definen como funcionales son

const add = (a, b) => a + b;
 
const result = add(1, 2); // Output is always 3

1.1. Por qué el método reduce() es importante para la programación funcional

El método reduce() se adhiere a los principios de la programación funcional en JavaScript porque realiza operaciones en un array sin modificar el array existente. Esto es especialmente cierto cuando estás reduciendo un array a un único valor o acumulando resultados basados en los elementos del array, porque no tienes que gestionar los valores acumulados fuera de la función. Además, no tiene efectos secundarios. Como resultado, es un método esencial para escribir código más limpio y mantenible.

2. Entendiendo el método reduce(): inicialización, índice y acumulador

El método reduce() es un método de array que recorre un array y ejecuta la función proporcionada (reducer) para cada elemento del array para producir un único valor de salida.

La sintaxis básica es

array.reduce(reducerFunction, initialValue);
 
// reducerFunction
array.reduce(((accumulator, currentValue, currentIndex, array) => returnValue), initialValue);

El initialValue es el valor inicial que se sumará al valor de retorno de la reducerFunction. Utilice 0 para obtener la suma de números, "" para obtener la cadena final, etc.

El reducerFunction es una función de devolución de llamada que toma cuatro parámetros.

  • accumulator (accumulator) - acumula el valor de retorno de aplicar la función a todos los elementos hasta el índice anterior.
  • currentValue (currentValue) - El valor del elemento al que se aplica actualmente la función.
  • index (currentIndex) - El índice de la matriz del elemento actual (opcional).
  • array (array) - Una referencia a la propia matriz (opcional).

Veamos un ejemplo sencillo para ver qué valores tendrá cada parámetro.

const numbers = [ 1, 2, 3 ]
 
numbers.reduce((accumulator, currentValue, currentIndex, array) => {
    console.log(`accumulator: ${accumulator}, currentValue: ${currentValue}, currentIndex: ${currentIndex}, array: ${array} `)
    return accumulator + currentValue
}, 0);
 
// Output:
// accumulator: 0, currentValue: 1, currentIndex: 0, array: 1,2,3
// accumulator: 1, currentValue: 2, currentIndex: 1, array: 1,2,3
// accumulator: 3, currentValue: 3, currentIndex: 2, array: 1,2,3
// 6

En la primera llamada a la función reductora con índice 0, el acumulador tiene un valor inicial de 0. La función reductora añade el valor actual 1 al valor del acumulador y lo devuelve, que se convierte en el nuevo valor del acumulador. Este proceso se repite hasta que el resultado final de la función reduce() devuelve el valor final del acumulador, 6.

En otras palabras, para descomprimir el comportamiento del ejemplo anterior, se vería así

const numbers = [ 1, 2, 3 ]
const reducerFunction = element => element
 
const returnValue = reducerFunction(numbers[0]) + reducerFunction(numbers[1]) + reducerFunction(numbers[2])
 
console.log(returnValue)
// Output: 6

2.1. Cuidado con las palabras clave break y continue

La mayoría de los métodos de array, incluyendo la función reduce(), no soportan las palabras clave break, continue que manipulan las operaciones transversales. Si no desea hacer nada con el elemento actual, como utilizar la palabra clave continue, puede utilizar una sentencia condicional para devolver el valor acumulado tal cual. En el ejemplo siguiente, pasamos por 3 sin acumular.

const numbers = [ 1, 2, 3 ]
const reducerFunction = (accumulator, element) => {
    console.log(`누산기: ${accumulator}, 현재값: ${element}`)
    if (element === 3) {
        return accumulator
    }
    return accumulator + element
}
 
numbers.reduce(reducerFunction, 0)
// Output: 3

3. Cómo utilizarlo para manipular objetos

El método reduce() también es útil para acceder a las propiedades de un objeto y realizar diversas operaciones sobre ellas. Puedes acceder a las propiedades del objeto directamente o utilizar un método ayudante como Object.entries().

Veámoslos uno a uno.

const people = [
    { name: 'Alice', age: 25 },
    { name: 'Bob', age: 30 },
    { name: 'Charlie', age: 25 },
    { name: 'David', age: 30 }
];
 
const groupedByAge = people.reduce((accumulator, currentValue) => {
    const ageGroup = currentValue.age;
    accumulator[ageGroup] = accumulator[ageGroup] || [];
    accumulator[ageGroup].push(currentValue);
    return accumulator;
}, {});
 
console.log(groupedByAge);
// Output:
// {
//  '25': [
//      { name: 'Alice', age: 25 },
//      { name: 'Charlie', age: 25 }
//  ],
//  '30': [
//      { name: 'Bob', age: 30 },
//      { name: 'David', age: 30 }
//  ]
// }

El ejemplo anterior accedía a la propiedad age de un objeto y realizaba una tarea para clasificar los objetos en dos grupos en función de su edad.

const grades = {
    math: 90,
    science: 80,
    history: 85,
    english: 95
};
 
const totalScore = Object.entries(grades).reduce((accumulator, [subject, score]) => {
    return accumulator + score;
}, 0);
 
console.log(totalScore); // Output: 350

Si necesita manipular múltiples valores de un único objeto, puede utilizar el método Objext.entries(). Este método manipula las propiedades del objeto y los valores de las propiedades como un único array, como se muestra arriba. Esto nos permite usar la función reduce() en objetos también, y se ve así, Las asignaciones desestructuradas, como [subject, score], pueden usarse para escribir código más conciso.

4. Ejemplos de aplicaciones reales como la eliminación de duplicados

En la sección Función JS filter() - 3. Deduplicación con filter(), también vimos la técnica de deduplicación como ejemplo de código. Con la función reduce(), también puedes escribir fácilmente código para eliminar elementos duplicados de un array.

Empecemos con el código.

const array = [1, 2, 3, 2, 4, 3, 5, 1];
 
const uniqueArray = array.reduce((accumulator, element) => {
  if (!accumulator.includes(element)) {
    accumulator.push(element);
  }
  return accumulator;
}, []);
 
console.log(uniqueArray);
// Output: [1, 2, 3, 4, 5]

El código anterior establece el valor inicial a un array vacío [] y luego añade un nuevo elemento a él si el elemento actual no existe en el array accumulator{js}. Utiliza el método Array.includes() para determinar la inclusión.

Compara esto con el método String.includes() utilizado en la sección Función JS filter() - 4. Definiendo funciones callback con includes().

Puedes ver que el array de resultados devuelto por la función reduce sólo saca elementos no duplicados.

5. Uso de funciones async callback

Hemos visto cómo utilizar funciones de callback asíncronas en métodos array en JS map() method - 6. Async callback: Asynchronous callback functions. El método map(), junto con el método Promise.all(), nos permitió escribir código que funcionaba de forma asíncrona + concurrente.

Sin embargo, el método reducer no puede utilizarse con funciones callback asíncronas porque no hay forma de soportar el comportamiento asíncrono. Para evitar esto, tenemos que definir nuestra propia función reduce personalizada que funcione de forma asíncrona utilizando la palabra clave async await y un objeto Promise.

Empecemos con el código de ejemplo.

const array = [1, 2, 3, 4, 5];
 
const asyncReduce = async (array, callback, initialValue) => {
  let accumulator = initialValue;
 
  for (const element of array) {
    accumulator = await callback(accumulator, element);
  }
 
  return accumulator;
};
 
const sumAsync = async (a, b) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(a + b);
    }, 1000);
  });
};
 
const calculateSum = async () => {
  const sum = await asyncReduce(array, sumAsync, 0);
  console.log(sum);
};
 
calculateSum();
// Output: 15

La función asyncReduce() del ejemplo recorre el array a través de la sintaxis for of, llama a la función de callback asíncrona, y await para que se completen todas las operaciones. La función de callback asíncrona arbitraria sumAsync() espera un segundo y devuelve el resultado de la suma. Finalmente, la función calculateSum() sirve como función principal que ejecuta la función asyncReduce().

Si ejecutas el código, al cabo de cierto tiempo obtendrás la suma de todos los números, 15.

6. Conclusión

El método reduce() de JavaScript es una herramienta potente y versátil para la programación funcional. Te permite realizar operaciones sobre arrays manteniendo principios como la inmutabilidad y la simplicidad. Utilízalo sabiamente junto con otros métodos de arrays, y asegúrate de que cuando escribas tu código, sea intuitivo y legible.

copyright for Javascript reduce

© 2023 All rights reserved.