DEV Community

Johnny Reina
Johnny Reina

Posted on

4

Intro to the filter function

this post was originally published on my Github Pages site on September 15th, 2017

This might sound a bit outlandish or ridiculous, but I seldom write loops nowadays. What I have found is that just about every programming language includes a set of methods or applicable functions that can replace just about every loop that I was previously writing. These higher-order functions are called map, filter, and fold.

Filter

The filter function takes a predicate, a function which accepts an item from your array and returns a boolean result, and returns a new array containing the elements that return true when passed through the predicate.

Baby steps

We'll start off with some easy examples:

const nums = [ 1, 2, 3, 4, 5 ]
nums.filter(num => num > 2)
// [3, 4, 5]
nums.filter(num => num % 2 === 0)
// [2, 4]
nums.filter(num => num !== 3)
// [ 1, 2, 4, 5]
view raw filter.baby.es6 hosted with ❤ by GitHub

Unlike its counterparts map and fold, filter's name immediately and obviously expresses what it does. Though it's a rather simple function, it is very powerful nonetheless.

Learning to crawl

Here's an example of filtering an array of objects:

const people = [ { name: 'Susan', age: 31, hobbies: [ 'Turtle Racing', 'Eagle Cuddling' ] },
{ name: 'Tom', age: 52, hobbies: [ 'Cobra Charming' ] },
{ name: 'Mary', age: 19, hobbies: [ 'Donkey Staring', 'Baboon Sniffing' ] },
{ name: 'Gwynyth', age: 96, hobbies: [ 'Cow Tipping', 'Whale Whispering', 'Rabbit Painting' ] } ]
people.filter(person => person.name === 'Mary')
// [ { name: 'Mary', age: 19, hobbies: [ 'Donkey Staring', 'Baboon Sniffing' ] } ]
people.filter(person => person.name === 'Fred')
// []
people.filter(person => person.age > 40)
/*
[ { name: 'Tom', age: 52, hobbies: [ 'Cow Tipping', 'Cobra Charming' ] }
, { name: 'Gwynyth', age: 96, hobbies: [ 'Whale Whispering', 'Rabbit Painting' ] } ]
*/
people.filter(person => person.hobbies.length === 2)
/*
[ { name: 'Susan', age: 31, hobbies: [ 'Turtle Racing', 'Eagle Cuddling' ] }
, { name: 'Mary', age: 19, hobbies: [ 'Donkey Staring', 'Baboon Sniffing' ] ]
*/

In the first filter, we are looking for people in the list whose name is Mary. Since there is only one person in the list with this name, we only get one result. Note that since filter always returns an array, we just got back an empty array when we looked for someone named Fred in the second filter. In the third example, we look for people whose age is greater than 40. Finally, in the last example, we look for people who have two hobbies.

If this is taking a bit to click, I'll show an example of filter done in an imperative style. This is a pattern I used to write quite often before I knew how to use filter.

const people = [ { name: 'Susan', age: 31, hobbies: [ 'Turtle Racing', 'Eagle Cuddling' ] },
{ name: 'Tom', age: 52, hobbies: [ 'Cow Tipping', 'Cobra Charming' ] },
{ name: 'Mary', age: 19, hobbies: [ 'Donkey Staring', 'Baboon Sniffing' ] },
{ name: 'Gwynyth', age: 96, hobbies: [ 'Whale Whispering', 'Rabbit Painting' ] } ]
const peopleNamedMary = []
for(let i = 0; i < people.length; i++) {
if(people[i].name === 'Mary') peopleNamedMary.push(people[i])
}
// [ { name: 'Mary', age: 19, hobbies: [ 'Donkey Staring', 'Baboon Sniffing' ] } ]
const peopleNamedFred = []
for(let i = 0; i < people.length; i++) {
if(people[i].name === 'Fred') peopleNamedFred.push(people[i])
}
// []
const peopleOlderThanForty = []
for(let i = 0; i < people.length; i++) {
if(people[i].age > 40) peopleOlderThanForty.push(people[i])
}
/*
[ { name: 'Tom', age: 52, hobbies: [ 'Cow Tipping', 'Cobra Charming' ] }
, { name: 'Gwynyth', age: 96, hobbies: [ 'Whale Whispering', 'Rabbit Painting' ] } ]
*/
const peopleWithTwoHobbies = []
for(let i = 0; i < people.length; i++) {
if(people[i].hobbies.length === 2) peopleWithTwoHobbies.push(people[i])
}
/*
[ { name: 'Susan', age: 31, hobbies: [ 'Turtle Racing', 'Eagle Cuddling' ] }
, { name: 'Mary', age: 19, hobbies: [ 'Donkey Staring', 'Baboon Sniffing' ] ]
*/

While these loops have the same result as the previous examples, they are much more explicit and there is much more typing involved.

Up and running!

These examples are pretty easy, right? Well, there really isn't a whole lot to it.

Out of the map-filter-fold family of functions, filter is the function I use the least in JavaScript. However, C#'s counterpart, Where, is definitely my workhorse when working in C#.

When I am filtering data based on multiple conditions, I like to define the predicates as named variables ahead of time. I've found that this improves the readability of the code tremendously, in addition to providing opportunities to reusing the pre-defined functions. Consider the following example:

const people = [ { name: 'Susan', age: 31, hobbies: [ 'Turtle Racing', 'Eagle Cuddling' ] },
{ name: 'Tom', age: 52, hobbies: [ 'Cobra Charming' ] },
{ name: 'Mary', age: 19, hobbies: [ 'Donkey Staring', 'Baboon Sniffing' ] },
{ name: 'Gwynyth', age: 96, hobbies: [ 'Cow Tipping', 'Whale Whispering', 'Rabbit Painting' ] } ]
const olderThanForty = person => person.age > 40;
const nameHasNoVowels = person => !/[aeiou]/i.test(person.name); // 'y' isn't a real vowel!
people
.filter(olderThanForty)
/*
[ { name: 'Tom', age: 52, hobbies: [ 'Cow Tipping', 'Cobra Charming' ] }
, { name: 'Gwynyth', age: 96, hobbies: [ 'Whale Whispering', 'Rabbit Painting' ] } ]
*/
.filter(nameHasNoVowels)
// { name: 'Gwynyth', age: 96, hobbies: [ 'Cow Tipping', 'Whale Whispering', 'Rabbit Painting' ] }

Since filter always returns an array, you can chain together your calls to filter and drill down to the data you want incrementally. You must be careful with your logic, though, especially when the filtering logic you are trying to apply requires mixing AND and OR logic.

When should I use filter?

This might not need to be said, but you should use filter when you want to reduce the items in a collection to only those items which meet specific criteria.

JavaScript is the worst! What other languages have filter?

Pretty much all the good ones. Though the names might be a bit different. In an effort to avoid plagiarism and only write what I really know about, I'll list out a few equivalent methods/functions that I know and have used here.

Language Function/Method
JavaScript Array.prototype.filter
C# IEnumerable.Where (as part of System.Linq)
Haskell filter
PHP array_filter
MongoDB db.collection.find

Alright, I'm convinced. When do I start?

Right now! Go!

The best way to get familiar with filter is to just start using it.

Sentry blog image

How I fixed 20 seconds of lag for every user in just 20 minutes.

Our AI agent was running 10-20 seconds slower than it should, impacting both our own developers and our early adopters. See how I used Sentry Profiling to fix it in record time.

Read more

Top comments (0)

SurveyJS custom survey software

JavaScript Form Builder UI Component

Generate dynamic JSON-driven forms directly in your JavaScript app (Angular, React, Vue.js, jQuery) with a fully customizable drag-and-drop form builder. Easily integrate with any backend system and retain full ownership over your data, with no user or form submission limits.

Learn more