Si controlamos el Array.map()
, una manera de ver el .reduce()
es verlo como un .superMap()
Cómo funciona
El reduce
, aparte del nombre, lo que hace es iterar un iterable al estilo forEach
, map
o filter
const myArr = [2, 2, 2, 2]
myArr.forEach(el => console.log(el))
myArr.map(el => console.log(el))
myArr.filter(el => console.log(el))
myArr.reduce(el => console.log(el))
Y todo esto de arriba da exactamente el mismo console.log
Bueno, no, todos excepto el reduce
const myArr = [2, 2, 2, 2]
myArr.forEach(el => console.log(el))
myArr.map(el => console.log(el))
myArr.filter(el => console.log(el))
myArr.reduce((acc, el) => console.log(el), '')
Ahora sí, ahora ya dan todos igual
La nomeclatura del reduce
es algo distinta, y esto es así porque viene a ser como el padre de las otras 3 funciones
O en otras palabras, podemos utilizar reduce
para emular el comportamiento de las demás funciones
Y cómo funciona?
Reduce
nos integra un acumulador, aunque el nombre puede confundir
Este acumulador en realidad es una variable que recibiremos en cada ciclo y que será persistente, y podremos hacer lo que queramos con ella
const myArr = ['hola', 'que tal', 'estamos', 'por aquí']
const resultado = myArr.reduce((acc, el) => {
return (acc += el + ' ... ')
}, '')
console.log(resultado) // "hola ... que tal ... estamos ... por aquí ... "
Es decir, el valor que retornamos es el valor de acc
que recibiremos en la próxima iteración, hasta el final que devolveremos el último valor de acc
Pero el valor de acc
es arbitrario
reduce
recibe 2 variables, podemos ponerle nombres que nos ayuden un poco
const myArr = ['hola', 'que tal', 'estamos', 'por aquí']
const resultado = myArr.reduce((frase, parte) => {
return (frase = frase + parte + ' ... ')
}, '')
console.log(resultado) // "hola ... que tal ... estamos ... por aquí ... "
Y podemos escribirlo de forma más compacta
const myArr = ['hola', 'que tal', 'estamos', 'por aquí']
const resultado = myArr.reduce((frase, parte) => frase + parte + ' ... ', '')
console.log(resultado) // "hola ... que tal ... estamos ... por aquí ... "
Por qué le llaman acumulador? Pues por esto, porque es una variable que acumula
Y esta variable no tiene por qué ser un string
, puede ser cualquier cosa
const myArr = ['hola', 'que', 'tal', 'estamos', 'por', 'aquí']
const resultado = myArr.reduce(
(str, el) => {
str.frase += el + ' ... '
str.palabras.push(el)
return str
},
{ frase: '', palabras: [] }
)
console.log(resultado)
// {
// frase: "hola ... que ... tal ... estamos ... por ... aquí ... ",
// palabras: ["hola", "que", "tal", "estamos", "por", "aquí"]
// }
Que el ejemplo no es de lo más útil que podamos hacer, pero nos sirve para ver que realmente puedes hacer lo que quieras, tienes total libertad
Otro ejemplo igual de útil?
Por ejemplo, para contar elementos de una estructura
const posts = [
{ type: 'text', content: 'hey yo' },
{ type: 'text', content: 'hey yu' },
{ type: 'blog', content: 'this is a blog' },
{ type: 'blog', content: 'very interesting content' },
{ type: 'text', content: 'hey ya' },
]
Cuántos elementos de tipo text
y de tipo blog
tenemos?
const posts = [
{ type: 'text', content: 'hey yo' },
{ type: 'text', content: 'hey yu' },
{ type: 'blog', content: 'this is a blog' },
{ type: 'blog', content: 'very interesting content' },
{ type: 'text', content: 'hey ya' },
]
const text_posts = posts.reduce((str, el) => (el.type === 'text' ? (str += 1) : str), 0)
const blog_posts = posts.reduce((str, el) => (el.type === 'blog' ? (str += 1) : str), 0)
console.log(text_posts) // 3
console.log(blog_posts) // 2
Muy sencillo, aunque estamos iterando dos veces el mismo array, no es lo más eficiente
const posts = [
{ type: 'text', content: 'hey yo' },
{ type: 'text', content: 'hey yu' },
{ type: 'blog', content: 'this is a blog' },
{ type: 'blog', content: 'very interesting content' },
{ type: 'text', content: 'hey ya' },
]
const { text: text_posts, blog: blog_posts } = posts.reduce(
(str, el) => {
str[el.type] += 1
return str
},
{
text: 0,
blog: 0,
}
)
console.log(text_posts) // 3
console.log(blog_posts) // 2
Ahora es más eficiente (pero definitivamente más ofuscado que antes)
Usos más sofisticados?
Lo podemos utilizar para piping (lo tienes en ésta entrada)
🙋♂️
Lista de correo: escribo algo de tanto en cuanto