reduce()
es uno de los array methods mas confusos de comprender en javascript, hasta la fecha me cuesta comprenderlos por poco, sobre todo para casos de uso avanzados. Por ello nace este post donde con ejercicios tratare de entender y compartir todo sobre reduce
Ejemplo #1: Sumar elementos de un arreglo
Quiza el ejemplo mas basico y mas ejemplificado de reduce
veamos:
Veamos lo que hace reduce
paso a paso:
- Indicamos que el valor inicial de
acc
es0
, entoncescurrent
toma el primer elemento del arreglonumeros
, osea5
; y los suma.
Iteración | acc | current |
---|---|---|
1ra | 0 | 5 |
2da | 5 | 12 |
3ra | 17 | 9 |
4ta | 26 | 2 |
5ta | 28 | 4 |
6ta | 32 | - |
En la 2da iteración
acc
tiene ahora el valor de5
y current es12
, la suma seria17
, que es el nuevo valor deacc
para la 3ra iteración.Continuamos haciendo este proceso hasta que el arreglo
numeros
no tenga mas elmentos. Resultado final:32
.
Ejemplo #2: Concatenar todos los elementos de un arreglo numérico
Dado un arreglo de numeros, concatenar todos sus elementos
Iteración | acc | current | Resultado parcial |
---|---|---|---|
1ra | '' | 1 | '1' |
2da | '1' | 2 | '12' |
3ra | '12' | 3 | '123' |
4ta | '123' | 4 | '1234' |
5ta | '1234' | 5 | '12345' |
6ta | '12345' | - | - |
En la 1ra iteracion
acc
es una cadena vacia que se concatena con el numero1
, ergo existe una conversion implicita de tipos, denumber
astring
.acc
ahora es'1'
comostring
que se concatena con el siguiente valor, un2
, dando como resultado12
.Se repite el proceso hasta que no queden valores en el arreglo.
Note la importancia del valor de inicializacion de
acc
Ejemplo #3: Sumatoria de coincidencias en arreglo de objetos
Dado el siguiente arreglo de objetos:
const voters = [
{name:'Bob' , age: 30, voted: true},
{name:'Jake' , age: 32, voted: true},
{name:'Kate' , age: 25, voted: false},
{name:'Sam' , age: 20, voted: false},
{name:'Phil' , age: 21, voted: true},
{name:'Ed' , age:55, voted:true},
{name:'Tami' , age: 54, voted:true},
{name: 'Mary', age: 31, voted: false},
{name: 'Becky', age: 43, voted: false},
{name: 'Joey', age: 41, voted: true},
{name: 'Jeff', age: 30, voted: true},
{name: 'Zack', age: 19, voted: false}
];
Contar cuantas personas votaron.
Iteración | acc | current | current.voted | acc + current.voted |
---|---|---|---|---|
1ra | 0 | {name:'Bob' , age: 30, voted: true} | true | 1 |
2da | 1 | {name:'Jake' , age: 32, voted: true} | true | 2 |
3ra | 2 | {name:'Kate' , age: 25, voted: false} | false | 2 |
4ta | 2 | {name:'Sam' , age: 20, voted: false} | false | 2 |
5ta | 2 | {name:'Phil' , age: 21, voted: true} | true | 3 |
6ta | 3 | {name:'Ed' , age:55, voted:true} | true | 4 |
7ma | 4 | {name:'Tami' , age: 54, voted:true} | true | 5 |
8va | 5 | {name: 'Mary', age: 31, voted: false} | false | 5 |
9na | 5 | {name: 'Becky', age: 43, voted: false} | false | 5 |
10ma | 5 | {name: 'Joey', age: 41, voted: true} | true | 6 |
11va | 6 | {name: 'Jeff', age: 30, voted: true} | true | 7 |
12va | 7 | {name: 'Zack', age: 19, voted: false} | false | 7 |
En el cuerpo del
reduce
hacemos una condicional ternariaacc + (current.voted ? 1 : 0)
donde sumamos1
aacc
sucurrent.voted
estrue
, caso contrario le sumamos0
Repetimos esta operación hasta que no queden objetos en el arreglo.
Recuerda que el valor de
current
en este ejemplo ya no es un primitivo, ahoracurrent
representa en cada iteración un objeto del arreglovoters
.
Ejemplo #4: Convertir una matriz en un arreglo
Iteración | acc | current | ...acc | ...current | [...acc, ...current] |
---|---|---|---|---|---|
1ra | [] | ["1", "2", "3"] | [] | "1", "2", "3" | ["1", "2", "3"] |
2da | ["1", "2", "3"] | [true] | "1", "2", "3" | true | ["1", "2", "3", true] |
3ra | ["1", "2", "3", true] | [4, 5, 6] | "1", "2", "3", true | 4, 5, 6 | ["1", "2", "3", true, 4, 5, 6] |
- El valor incial de
acc
ya no es un simple valor, ahoraacc
de entrada es un arreglo vacio. - Usamos
spread operator
para concatenar las copias de los arreglosacc
ycurrent
en cada iteración.
Ejemplo #5: GroupBy con reduce
Dado el siguiente arreglo de objetos:
const voters2 = [
{name:'Bob' , age: 30, voted: true},
{name:'Jake' , age: 32, voted: true},
{name:'Kate' , age: 25, voted: false},
{name:'Sam' , age: 20, voted: false},
{name:'Phil' , age: 21, voted: true},
{name:'Ed' , age:55, voted:true},
{name:'Tami' , age: 54, voted:true},
{name: 'Mary', age: 31, voted: false},
{name: 'Becky', age: 43, voted: false},
{name: 'Joey', age: 41, voted: true},
{name: 'Jeff', age: 30, voted: true},
{name: 'Zack', age: 19, voted: false}
];
Agrupar y contar la cantidad de personas de la siguiente manera:
- Cuantas personas jovenes hay (entre 18 y 25 años) y cuantas de estas personas jovenes votaron.
- Cuantas personas adultas hay (entre 26 y 35 años) y cuantas de estas personas adultas votaron.
- Cuantas personas maduras hay (entre 36 y 55 años) y cuantas de estas personas maduras votaron.
El valor inicial de
acc
es un objeto con ciertas propiedades que nos interesan.En cada iteracion se evaluan las condiconales y se incementan los valores del objeto.
Es importante que la funcion retorne algo puesto que sino lo hacemos tendremos un error, en este ejemplo hacemos
return {...acc}
para regresar una copia del objeto incial sino se cae en las condicionales.
Este ejemplo es suficientemente claro tener una tabla explicativa
Ejemplo #6: Promedios con reduce
Dado el siguiente arreglo :
const nums = [
[1,6,9,2,5,4],
[50,67,3,80,24,17],
[100,77,50,35,12,56]
];
Obtener en un nuevo arreglo los promedios de cada uno de ellos.
Iteración | acc | current | Resultado parcial | item.length |
---|---|---|---|---|
1ra | [] | 1 | 1 | 6 |
2da | 1 | 6 | 7 | 6 |
3ra | 7 | 9 | 16 | 6 |
4ta | 16 | 2 | 18 | 6 |
5ta | 18 | 5 | 23 | 6 |
6ta | 23 | 4 | 27 | 6 |
- Usamos un
map
para iterar sobre cada arreglo. En la 1ra iteración nos enfocamos en[1,6,9,2,5,4]
. - Obtenemos la sumatoria que es
27
y luego lo dividimos entre el numero de elementos6
, obteniendo[4.5]
-
map
vuelve a iterar y ahora hacemos lo mismo con[50,67,3,80,24,17]
y luego con[100,77,50,35,12,56]
- Resultado final:
[ 4.5, 40.166666666666664, 55 ]
Ejemplo #7: Contador de boleanos
Dado el arreglo:
const booleans = [true, true, false, true, false, true];
Contar cuantos valores true
hay.
Iteración | acc | current | Resultado parcial |
---|---|---|---|
1ra | 0 | true | 1 |
2da | 1 | true | 2 |
3ra | 2 | false | 2 |
4ta | 2 | true | 3 |
5ta | 3 | false | 3 |
6ta | 3 | true | 4 |
- Recorremos el arreglo y cuando se encuentra un
true
incrementamos en uno el valor deacc
. Caso contrario no le sumamos nada.
Ejemplo #8: Contador mejorado
Es posible mejorar el ejemplo del contador inicializando el acc
con un objeto y usando propiedades dinamicas con la sintaxis obj[propiedad]
.
Ejemplo #9: Convertir arreglos a objetos
Dado un arreglo de objetos:
const personas = [
{nombre:"Cristian", edad:25, sexo:"M"},
{nombre:"Ana", edad:20, sexo:"F"},
{nombre:"Fernando", edad:15, sexo:"M"},
{nombre:"Alejandra", edad:11, sexo:"F"},
];
Convertirlo a algo como:
{
Cristian: {
edad:25,
sexo:"M"
}
}
- En cada iteración el valor de
current
sera uno de los obejtos del arreglo empezando por{nombre:"Cristian", edad:25, sexo:"M"}
- Para cada
nombre
accedemos acurrent.nombre
del objetoacc
que declaramos como vacio. - Imprimimos las llaves
sexo
yedad
.