Updated Apr 16 2018
Loops are generally used, in any programming language, to perform operations on arrays: given an array you can iterate over its elements and perform a calculation.
Letβs see how to pick common needs and perform them using a Functional Programming approach, as opposed to using loops.
NOTE: I donβt recommend one approach over the other. I just want to introduce different ways to perform the same thing and maybe introduce you to new functions which you might have never used until now.
map
, filter
, reduce
, find
Those are 3 really powerful array functions:
map
returns an array with the same length,filter
as the name implies, it returns an array with less items than the original arrayreduce
returns a single value (or object)find
returns the first items in an array that satisfies a conditionmap
, filter
and reduce
were introduced in ES5, so you can safely use them as implemented in every browser since years.
find
was introduced in ES6/ES2015.
They offer a more declarative approach, rather than an imperative approach (describe what should happen, not write every tiny bit of processing that should happen)
map
A loop would look like this:
const performSomething = (item) => {
//...
return item
}
const items = ['a', 'b', 'c']
items.forEach((item) => {
performSomething(item)
})
With a declarative approach, you tell JavaScript to perform something on every element using:
const items = ['a', 'b', 'c']
const newArray = items.map((item) => performSomething(item))
This generates a new array, without editing the original one (what we call immutability)
Since we use a single function in the map callback function, we can rewrite the sample as:
const items = ['a', 'b', 'c']
const newArray = items.map(performSomething)
Sometimes you need to look for a specific item in the array, and return it.
This is how you would do so with a loop:
const items = [
{ name: 'a', content: { /* ... */ }},
{ name: 'b', content: { /* ... */ }},
{ name: 'c', content: { /* ... */ }}
]
for (const item of items) {
if (item.name === 'b') {
return item
}
}
Here is the non-loop version, using find()
(ES6+):
const b = items.find((item) => item.name === 'b')
Here is the same functionality using filter()
(ES5+):
const b = items.filter((item) => item.name === 'b').shift()
shift() returns the first item in the array without raising an error if the array is empty (returns
undefined
in that case).
Note: shift()
mutates the array, but the array it mutates is the one returned by filter()
, not the original array. If this sounds unacceptable, you can check if the array is not empty and get the first item using b[0]
.
For learning purposes (does not make much sense in practice), here is the same functionality using reduce()
:
const items = [
{ name: 'a', content: { /* ... */ }},
{ name: 'b', content: { /* ... */ }},
{ name: 'c', content: { /* ... */ }}
]
const b = items.reduce((result, item) => {
if (item.name === 'b') { result = item }
return result
}, null)
filter()
and reduce()
will iterate over all the array items, while find()
will be faster.
Use reduce()
to get a single value out of an array. For example sum the items content.value
property:
const items = [
{ name: 'a', content: { value: 1 }},
{ name: 'b', content: { value: 2 }},
{ name: 'c', content: { value: 3 }}
]
using a loop:
let count = 0
for (const item of items) {
count += item.content.value
}
can written as
const count = items.reduce((result, { content: { value } }) => result + value, 0)
I wrote an entire book on this topic π
I also got a super cool course π
© 2023 Flavio Copes
using
Notion to Site.
Follow on Twitter
Solopreneur? Wannabe? Adventure awaits