Functional Basics #2: Filter
Kevin Smith 🏴
Posted on October 20, 2019
Welcome back! In the second part of this mini-series on functional programming basics, I'll be taking a quick look at another common array function - filter
.
If you haven't already read it, I recommend starting with the first article in this series, Functional Basics #1: Map. I'll be building on some ideas as the series progresses.
What is it?
Let's again start by defining what filter
does: it takes an array and removes some elements, leaving only the elements that we're interested in. Okay, but how does it do that? We'll first take a look at how we'd do it in the imperative style, using for
loops:
const myArray = [1, 2, 3, 4, 5]
let oddNumbers = []
for (let i = 0; i < myArray.length; i++) {
if (myArray[i] % 2 === 1) {
oddNumbers.push(myArray[i])
}
}
// myArray: [1, 2, 3, 4, 5]
// oddNumbers: [1, 3, 5]
As we did with map
in Part 1, we can tidy this up by extracting some of the logic from our loop - specifically, we can extract the condition of the if
statement to make it clear what that condition actually means:
const isOdd = num => num % 2 === 1
const myArray = [1, 2, 3, 4, 5]
let oddNumbers = []
for (let i = 0; i < myArray.length; i++) {
if (isOdd(myArray[i])) {
oddNumbers.push(myArray[i])
}
}
// isOdd(1): true
// isOdd(2): false
// myArray: [1, 2, 3, 4, 5]
// oddNumbers: [1, 3, 5]
Having extracted the logic to an isOdd
function, you can now see clearly that we're checking for odd numbers in our if
statement.
A function like
isOdd
which determines whether a value meets a certain criteria is known as a predicate function.
But we still have a for
loop which is a potential opportunity to introduce bugs, and we still have to mutate our oddNumbers
array by adding results to it one by one.
If we try to describe what we want in a declarative way, we could say, "take myArray
and produce a new array which only contains the elements for which isOdd
is true". And filter
allows us to express exactly that:
const isOdd = num => num % 2 === 1
const myArray = [1, 2, 3, 4, 5]
const oddNumbers = myArray.filter(isOdd)
// myArray: [1, 2, 3, 4, 5]
// oddNumbers: [1, 3, 5]
Calling
filter
on an array, and passing it a predicate function, returns a new array containing the elements for which the predicate returnstrue
.
Also note the original array is not mutated byfilter
- as withmap
, the result must be assigned to a variable or used immediately!
Also, as with map
, we're not restricted to using our own functions as the predicate. We can use any function which takes one value and returns true
or false
. Javascript has a global function isNaN
which returns true
if the value passed to it is not a number, and false
if it is. Let's use that to filter out numbers from an array:
const myArray = [1, 2, 'apple', 3, 'orange', 4, 'banana']
const arrayWithoutNumbers = myArray.filter(isNaN)
// myArray: [1, 2, 'apple', 3, 'orange', 4, 'banana']
// arrayWithoutNumbers: ['apple', 'orange', 'banana']
And that pretty much sums it up for filter
. Again, aside from looking specifically at filter
, it's important to reinforce the idea that functions are just values which can be passed to and returned from other functions, like any other value. Stay tuned for Part 3!
If you found this article helpful, follow me! I'll be adding more articles in this series soon. Liked it? Like it ❤️! Suggestions/improvements? Comment ⬇️! :)
Posted on October 20, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
March 6, 2024