Las bondades del método reduce() en JavaScript.
Tags: javascript, webdev, spanish
Published: 2020-09-20 15:18:29

`reduce()` es un método bastante peculiar, ampliamente usado pero al mismo tiempo incomprendido por las comunidades de desarrollo. Junto con `map()` y `filter()` completan lo que me gusta denominar como la **Trinidad de los métodos JavaScript**.

En este pequeño post trataré de resumir y explicar las principales características del método `reduce()` con ejemplos prácticos. 

Al igual que `map()` y `filter()`, `reduce()` itera sobre un arreglo dado.

## **Sintaxis**
```js
array.reduce( (acc, item, index, arr)=>{
//cuerpo de la funcion
}, inicilizador del acumulador)
```
`reduce()` recibe un callback con 4 parámetros:

* **acc**: variable acumuladora donde se almacenarán valores parciales en cada iteración del arreglo.
* **item**: elemento actual del arreglo que se itera.
* **index**: posición del elemento anterior mencionando.
* **arr**: arreglo como tal, sobre el cual se trabaja. 

En la práctica, casi para cualquier caso se uso se acostumbra solo usar la variable `acc` e `item`, por lo que una sintaxis más resumida se vería de la siguiente manera: 

```js
array.reduce( (acc, item)=>{
//cuerpo de la funcion
}, inicilizador del acumulador)
```

> *El inicializador del acumulador se explicará a detalle con los ejemplos practicos.*

## **Características de `reduce()`**
* `reduce()` reduce (valga la redundancia) el arreglo a un solo valor, en otras palabras, devolverá un solo valor.
* Ejecuta un callback para cada elemento del arreglo.
* El valor de retorno de la función se almacena en una variable acumuladora (`acc`).
* No se ejecuta en arreglos vacíos.
* Es inmutable, no altera ni modifica el arreglo original.

Basta de conceptos teóricos, ahora analicemos ejemplos prácticos: 

Imaginemos que tenemos un array de números y deseamos sumar todos sus valores, podríamos usar `reduce()` de la siguiente manera:

```js
let numeros =[2,9,7,16,3,78];
let suma = numeros.reduce((acc,numero) => acc + numero);
console.log(suma);
//salida: 115
``` 

Expliquemos a detalle que sucedió acá:

Al no usar un valor de inicialización, `acc = 2`, por ser el primer elemento de nuestro arreglo. 
La iteración del arreglo, por ende, comenzará desde el index 1, osea, el número 9: `numero = 9`
La siguiente tabla explica el flujo del programa: 

| Iteración     | **acc**           | **numero**       | **acc + numero** |
| ------------- | ------------- |------------- |------------- |
| 1ra iteración | 2             |       9      | 11           |
| 2da iteración |11             |       7      | 18           |
| 3ra iteración |18             |       16     | 34           |
| 4ta iteración |34             |       3      | 37           |
| 5ta iteración |37             |       78     | **115**         |

Analizando iteración a iteración se comprende mucho mejor de donde sale el resultado final.

Veamos otro ejemplo:
Imaginemos que tenemos un arreglo de objetos que contienen pedidos de comida, entonces el chef nos pide que le indiquemos cuantos son los pedidos cuyo plato principal sea "sajta", ¿cómo podríamos hacer esto con `reduce()`? El arreglo de objetos es el siguiente:

```js
let pedidos = [
  {entrada:'ensalada de pepinos', principal: 'sajta', postre: "platano"},
  {entrada:'ensalada de tomates', principal: 'silpancho', postre: "helado"},
  {entrada:'ensalada simple', principal: 'sajta', postre: "yogurt"},
  {entrada:'ensalada simple', principal: 'anticucho', postre: "yogurt"},
  {entrada:'ensalada de tomates', principal: 'sajta', postre: null}
];
```
> *La sajta es un plato típico boliviano elaborado en base a pollo, ají, papas, y salsa*

Una posible solución es la siguiente:

```js
let cantidadSajta = pedidos.reduce((contador,pedido)=>{
  if(pedido.principal === "sajta")
    return contador+1;
  else
    return contador;
},0)
console.log(cantidadSajta); //salida: 3
```
Podemos observar que en este ejemplo si escribimos una inicialización para la variable contador que es 0, (`contador = 0`). Esto hace que el iterador recorra el arreglo desde el índice 0 y no desde el índice 1 como vimos en el anterior ejemplo. 

## **Encontrar el mínimo o máximo**
Los métodos `min()` y `max()` de Math usadas con `reduce()` facilitan encontrar el mínimo y máximo en un arreglo de números:

```js
let numeros =[8,3,7,9,4,0];
const max = numeros.reduce((acc,numero) => Math.max(acc,numero))
console.log(max); //salida: 9
```

```js
let numeros =[8,3,7,9,4,0];
const min = numeros.reduce((acc,numero) => Math.min(acc,numero))

console.log(min); //salida: 0
```

## **Trabajar con arreglos anidados**
Imaginemos que contamos con un arreglo anidado y necesitamos convertirlo en un arreglo plano.

```js
let numeros =[1,2,[3,4,5],6,7,[8],[9,10]];
const planos = numeros.reduce((acc,item) =>{
  return acc.concat(item)
},[]);

console.log(planos);
//salida: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
```

## **Conclusiones**
* `reduce()` itera y compara cada elemento de un arreglo, aplicando un callback y devolviendo un solo valor.
* El callback recibe 4 parámetros pero en la práctica solo usamos 2: `acc` e `item`.
* Es un método inmutable.

---

## **Referencias**

* https://www.youtube.com/watch?v=VVySn87s8Eo
* https://www.w3schools.com/jsref/jsref_reduce.asp
* https://www.youtube.com/watch?v=0y5lXGYMEw0


![link](https://media.giphy.com/media/26AHC0kdj8IeLkmBy/giphy.gif)