CodeNewbie Community 🌱

Discussion on: Another way to understand JavaScript's array.reduce

Collapse
 
bholmesdev profile image
Ben Holmes • Edited

Hey thanks Robert! That's a totally fair question. I've def seen nested reduce loops before, but it can be difficult to read if you throw everything together without helper functions.

So this is a little sketchy:

const songsByAlbum = [
  ['Rap Snitches Knishes', 'Beef Rap', 'Gumbo'],
  ['Accordion', 'Meat Grinder', 'Figaro'],
  ['Fazers', 'Anti-Matter', 'Krazy World']
]
songsByAlbum.reduce((songsAsString, album) => {
  // Flatten our album strings to a big string of songs across *all* albums
  return songsAsString + album.reduce((albumAsString, song) => {
    // Flatten album of songs to a string of songs
    return albumAsString + " " + song
  }, "")
}, "")
Enter fullscreen mode Exit fullscreen mode

...but this is a little better!

const flattenToSongs = (songs) => {
  return songs.reduce((songsAsString, song) => {
    return songsAsString + song
  }, "")
}

songsByAlbum.reduce((songsAsString, album) => {
  return songsAsString + flattenToSongs(album)
}, "")
Enter fullscreen mode Exit fullscreen mode

That said, you sometimes don't even need reduce for "stringifying" lists. We could totally do something like this instead:

songsByAlbum.map(album => {
  return album.join(" ") // join our list into a string separated by spaces
}).join(" ") // join this list of "album strings" to a big string
Enter fullscreen mode Exit fullscreen mode

PS: if you're using a nested reduce because you have arrays within arrays, there's a new helper in JS to "flatten" to a single array! It's called array.flat. More on that here

Collapse
 
r002 profile image
Robert Lin • Edited

Very cool, thanks for sharing, Ben! I never knew about array.flat until today. Very neat. 👍

Everyday, I seem to find a new use for array.reduce though. It's seriously the gift that just keeps giving! 😄 Just this morning, I was searching for an equivalent to Python's counter data structure in JS and found this:

var arr = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4]

const map = arr.reduce((acc, e) => acc.set(e, (acc.get(e) || 0) + 1), new Map())

console.info([...map.keys()])
console.info([...map.values()])
console.info([...map.entries()])
Enter fullscreen mode Exit fullscreen mode

What a beauty! What a time to be alive!! 🚀

Source: stackoverflow.com/a/57028486

Thread Thread
 
bholmesdev profile image
Ben Holmes

Haha yeah, love the enthusiasm 😁

Agreed, reduce is for a lot more than just reduce-ing arrays to something smaller (like a number of a string). That's why some languages like Rust and Kotlin call it "fold." That's because you're "folding" something of one data type (like an array) into something of another data type (like a Map in your example). Doesn't mean we've reduced it, we've just changed it into something different!