Functional Basics #2: Filter
Tags: beginners, functional
Published: 2019-10-20 17:33:15

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](https://dev.to/kvsm/functional-basics-1-map-2d0a). 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:

```js
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:

```js
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:

```js
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 returns `true`.
> Also note the original array is not mutated by `filter` - as with `map`, 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:

```js
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 ⬇️! :)_