reduce es un método que puede ser difícil de entender, especialmente con todas las explicaciones vagas que se pueden encontrar en la web. Hay muchos beneficios para entender la reducción, ya que a menudo se usa en la administración del estado (piense en Redux).

La firma para el método reduce de un arreglo en JavaScript es:

arr.reduce(callback, initialValue);

Terminología

reduce viene dado por la terminología de reducir y acumular. El acumulador es el valor con el que terminamos y el reductor es la acción que realizaremos para llegar a un valor.

Debe recordar que un reductor solo devolverá un valor y un solo valor, por lo tanto, el nombre reduce.

Tome el siguiente ejemplo clásico:

const valor = 0; 

const numeros = [5, 10, 15];

for(let i = 0; i < numeros.length; i++) {
  valor += numeros[i];
}

Lo anterior nos dará 30 (5 + 10 + 15). Esto funciona bien, pero podemos hacerlo con reduce en su lugar, lo que nos evitará mutar nuestra variable de valor.

El siguiente código también generará 30, pero no mutará nuestra variable de valor (que ahora hemos llamado valorInicial)

/* Este será nuestro punto incial*/
const valorInicial = 0;

/* arreglo de numeros */
const numeros = [5, 10, 15];

/* el método reduce toma el acumulador y el item siguiente */
const reducer = (acumulador, item) => {
  return acumulador + item;
};

/* ahora pasamos areduce nustra funcion para reducir. */
const total = numeros.reduce(reducer, valorInicial)

El código anterior puede parecer un poco confuso, pero debajo del capó no hay magia. Agreguemos un console.log en nuestro método reductor que generará el acumulador y los argumentos del elemento.

La siguiente captura de pantalla muestra lo que se ha registrado en la consola:

acumulador es: 0 item es: 5
acumulador es: 5 item es: 10 
acumulador es: 1 5item es: 15 

Entonces, lo primero que notamos es que nuestro método se llama 3 veces porque hay 3 valores en nuestra matriz. Nuestro acumulador comienza en 0, que es nuestro valor inicial que pasamos para reducir. En cada llamada a la función, el artículo se agrega al acumulador. La última llamada al método tiene el valor acumulador de 15 y el artículo es 15, 15 + 15 nos da 30, que es nuestro valor final. Recuerde que el método reductor devuelve el acumulador más el artículo.

Así que ese es un ejemplo simple de cómo usarías reducir, ahora veamos un ejemplo más complicado.

Aplanar y reducir

Digamos que tenemos el siguiente arreglo:

const arreglo = [1, 2, [3, 10, [11, 12]], [1, 2, [3, 4]], 5, 6];

Y digamos por alguna loca razón, JavaScript ha eliminado el método .flat, por lo que debemos aplanar esta matriz nosotros mismos.

Entonces, escribiremos una función para aplanar cualquier matriz, sin importar cuán profundamente anidadas estén:

function aplanarArreglo(data) {
  //nuestro valor inicial es un arreglo vacio
  const valorInicial = [];

  // llamar a reduce en toda la data
  return data.reduce((total, valor) => {
    // Si el valor es un arreglo llamar reduce recursivamente
    // Si no solo concatenar el valor
    return total.concat(Array.isArray(valor) ? aplanarArreglo(valor) : value);
  }, valorInicial);
}

Si pasamos el arreglo de números a la función que creamos esto es lo que obtenemos:

0: 1
1: 2
2: 3
3: 10
4: 11
5: 12
6: 1
7: 2
8: 3
9: 4
10: 5
11: 6
length: 12

Este es un gran ejemplo de cómo podemos hacer que una operación muy común sea bastante simple.

Veamos un ejemplo más.

Cambiar la estructura de un objeto

Entonces, con el lanzamiento del nuevo juego de Pokemon, supongamos que tenemos un servidor que nos envía una variedad de objetos de Pokemon de esta manera:

const pokemon = [
  { name: "charmander", type: "fuego" },
  { name: "squirtle", type: "agua" },
  { name: "bulbasaur", type: "hierba" }
]

Y queremos cambiar este objeto para luzca así:

const pokemonModificado = {
  charmander: { type: "fuego" },
  squirtle: { type: "agua" },
  bulbasaur: { type: "hierba" }
};

Para llegar a esa salida deseada, hacemos lo siguiente:

const mapaDesdeArreglo = data =>
  data.reduce((acc, item) => {
    //add object key to our object 
    acc[item.name] = { type: item.type };
    return acc;
  }, {});

Categorized in:

Tagged in:

, ,