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((acc, el) => console.log(el), '')
La nomenclatura cambia un poco porque incluye un acumulador, una variable que recibiremos en cada ciclo y que será persistente
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
, y el valor inicial de acc
lo ponemos al final (aquí ''
pero puede ser cualquier variable)
Un ejemplo para ver cómo de versátil es el asunto:
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í"]
// }
Otro ejemplo para contar tipos de palabras
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 versátil, aunque estamos iterando dos veces el mismo array y seguro que se puede mejorar (o no)
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 sólo hacemos una iteración … pero el resultado es más ilegible, yo casi que prefiero la versión anterior