Swift — Filtering: A Real Example

Nicolas Savoini
Level Up Coding
Published in
4 min readJun 26, 2020

--

Photo by Nathan Dumlao on Unsplash

In any language, you can manage lists of things. Most likely, if you have a list, then at some point you will have to filter it. And most likely, you will have to filter it multiple times on numerous criteria. Let’s start with the basics.

One Filter, One Time

Now is the right time to talk about Higher-Order functions (Wiki). A Higher-Order function is a function that takes another function as its parameter. It could also be a function that returns a function, but we won’t be talking about that. A function that takes a function. It may seem steep at first, but once you see it, you’ll get it.

The easiest way to filter data is to create a new list and only copy the element you want.

You can put this into a function and use it every time. But thanks to Higher-Order functions, we can now do it much faster.

The filter function takes a function and applies it to all elements. Then, we use the variable bookBefore2020HOF to store the result.

You can find a lot of articles on this on Medium and the internet. If you aren’t familiar with the concept already, I strongly recommend checking out other articles for more explanation.

Multiple filters, multiple times.

Let’s dive into the topic at hand: How to filter a list on multiple criteria. Out list of books will have to be filtered on three different criteria (year, favorite, author first name). You can apply all requirements at the same time, or any other possibilities.

The eight options are:

  • No Filter
  • Filter 1 only
  • Filter 2 only
  • Filter 3 only
  • Filter 1 and Filter 2
  • Filter 1 and Filter 3
  • Filter 2 and Filter 3
  • Filter 1, Filter 2 and Filter 3

Let’s try not to write eight different functions. Let’s write only one function.

Our function will take the array and a Filter object that we will create.

Our Filter structure will represent the three criteria.

You can see the Favorite is an Enum. Here the code.

Every time you have a filter on a boolean, you have only two possibilities: YES and NO. That’s why we have booleans;).

But if you consider the fact that the filter can, or cannot, be applied, then you have three possibilities: YES, NO, and NO FILTER.

In this case, using an Enum is faster than managing IF cases.

We got the structure and the necessary enum to support it. Let’s move to the function. The function will use the array and the structure SearchingBook. The output of the method will be a new array with the data filtered.

We got the signature:

func filterBooks(books: [Book], by filters: SearchingBook) -> [Book]

For the code, you have two logic here.

You can start from an empty array, then add the book that matches the filters. Or you can start from a copy of the collection and remove the book that doesn’t match. The first method will need to handle duplicate. It’s not difficult, but it’s an extra step we can avoid.

Let’s go with the second choice.

As the first filter is simple, we will apply it directly.

We take our full list, and we apply the first filter. We use the double condition to handle the No Filter. In case the value is 0, the expression will always be true, and we will keep all the books.

Our second filter is on the Favorite field.

We use ENUM to handle all three possibilities.

If we want only the favorite books, we remove the non-favorites. If we want only the non-favorite books, we remove all the favorites.

Finally, if we want all the books, we exit the switch without removing anything.

I’m sure you notice the use of removeAll(where:), another Higher-Order function. The name says it all. It removes all the elements from a list that match a specific condition.

The last filter is on the author’s first name. We will use a mix of both previous filters. We’ll use an IF statement to handle the No Filter case, and the removeAll(where:) Higher-Order function to filter the books.

Now that we applied our three filters, we can return the data.

return bookFiltered

The full function

Let’s recap what we have:

  • A structure to handle the different filters
  • An enumeration to handle boolean filters
  • A function that mixes them all to get our data filtered

First, you can use your function all the time, filter or no filter.

No more IFs to handle all the possibilities. It’s also easier to add a new filter. You only need to update the structure and the function, and that’s it.

Second, this works very well with SwiftUI ;).

You need to map your Filter Buttons to the structure and use the function in your list. And that’s it, nothing else.

When the user activates a filter, the data is filtered and rendered. If the user deactivates all selections, all the data will be displayed.

You can find my playground project here: Playground.

--

--

Passionate geek, I have few apps on the AppleStore and a lot of ideas:) write about Tech and Life. nicolas.savoini@mac.com