A good[ish] website
Web development blog, loads of UI and JavaScript topics
A beginner-friendly guide into the JavaScript’s reduce method. Spiced up with analogies and examples.
JavaScript provides some handy Array methods, like, map
, filter
, includes
, some
, and every
, just to mention few.
But there’s a sane limit of how many custom methods you can have in a language. Thank god JavaScript is not like PHP, where you can just type a sentence and slap parens at the end and et voilà, it probably does what you want:
// Example of a typical native PHP function
plz_make_that_thing_like_backwards_and_then_tally_them_up_after()
Rather than being a collection of functions, JavaScript is a programming languages which provides versatile methods like reduce. Reduce is the Swiss army knife of array methods, a higher order function that lets you build your own tools.
Higher order function is a function that takes a function as a parameters.
A good way to look at reduce
is to compare it to a map
, it has two differences:
var foo = ['foo', 'bar'].map((currentValue, index, array) => {
return // Do something...
})
var bar = ['foo', 'bar'].reduce((previousValue, currentValue, index, array) => {
return // Do something...
}, {})
previousValue
, also referred to as accumulator
.initialValue
, which is not always needed, but it can be for example an empty object {}
or 0
.And this gives it two features map
doesn’t have:
callback
previousValue
callback
function produced on its previous iteration. This concept is in the heart of reduce.currentValue
map
.currentIndex
map
.array
map
.initialValue
callback
. If no initialValue
is supplied, the first element in the array will be used as the initial accumulator value and skipped as currentValue
.Below are some examples to illustrate how it actually works.
The most basic example is to sum up all the values in an array:
const coolNumbers = [69, 420, 666]
const holyNumber = coolNumbers.reduce((total, amount) => {
return total + amount
})
console.log(holyNumber) // 1155 🔥
The formula for an average is: sum of all the values
/ total amount of items
.
Here’s the logic in English:
total += amount
.total
.const moneys = [76.21, 420.69, 86.54]
const average = moneys.reduce((total, amount, index, array) => {
total += amount
const isLast = index === array.length - 1
if (isLast) return total / array.length
return total
})
console.log(average) // 194.48
This is a great example, because it uses all four of the callback’s arguments.
This is kind of cool, literally the only array method that can do this in JavaScript. Here we need to use the second param of the reduce method, the initialValue
.
Maybe we have a nested array structure of ISO-2 country codes and the country names, and we’d like to turn it into an object where the country code is the key, and country’s name the value.
{}
as the second parameter, this will be the value of the accumulator
on the first run.accumulator
is spread at the end.const countries = [
['ch', 'Switzerland'],
['de', 'Germany'],
['fr', 'France']
]
const regions = countries.reduce((accumulator, [countryCode, name]) => {
return { [countryCode]: name, ...accumulator }
}, {})
console.log(regions)
// { fr: "France", de: "Germany", ch: "Switzerland" }
With reduce
it’s handy to find all occurrences of the same number from an array:
const numbers = [1, 1, 2, 3, 4, 4, 4, 5, 5, 5, 5]
const occurrences = numbers.reduce((accumulator, randomNumber) => {
accumulator[randomNumber] = ++accumulator[randomNumber] || 1
return accumulator
}, {})
console.log(occurrences)
// { '1': 2, '2': 1: '3': 1, '4': 3, '5': 4 }
This can be handy for example when you’re trying to visualize some data, or figure out if a set of random numbers actually is random.
There’s a whole debate to be had if we should use reduce
at all, some people think it’s too nebulous, because everything that reduce can do can be done with for
loops.
I’ve embedded here a really nice episode of the HTTP 203 podcast with the topic of "Is reduce bad?" It’s worth the watch, there’s some nice nicknacks there.
They reason that junior devs don’t use reduce because it’s complex, and properly marinated seniors don’t use reduce because the pendulum has already swung into its other apex.
Also, there’s a certain (false) purity with reduce and array methods that is somehow appealing, by having one long, unbreakable chain where you process things. When using for
loops you need set the initial value into a separate variable at first, which is totally fine, but there’s a weird... what do you call it? kind of destructive, OCD driven, need for things to be concise and neatly packaged.
Hope this was helpful. Thanks for reading.
Comments would go here, but the commenting system isn’t ready yet, sorry.