Higher Order Functions in Swift – reduce, contains, allSatisfy, removeAll

April 22nd, 2021

⏱ Reading Time: 6 mins

Welcome to the fourth post in the series about higher order functions in Swift. Today I’m going to present more of these functions available to use in Swift, which, like all the rest, can really help us write cleaner and shorter code.

Before I dive into the main content of the post, here’s a summary of the previous articles on that series:

Today on the menu are the reduce, contains, allSatisfy and removeAll higher order functions. Let’s go through them one by one.

The reduce higher order function

The reduce higher order function has a simple purpose; to produce a single value out of the elements of a collection, based on calculations that we provide it with.

Let’s see what that means and how it works using a straightforward example. Suppose that we have the following array with the average temperatures per day during a week (in Celsius degrees):

In the end of the week we want to calculate the average temperature of all days. To do that, it’s necessary to get the sum of all temperatures and then divide by the number of days (7). A custom implementation to perform that calculation would look like this:

Although that’s not wrong, we can do much better using the reduce higher order function, and eventually end up with on line only, instead of five that we have here.

Let’s see reduce at its expanded form first:

Like any other higher order function, reduce is accessible through the collection object; that’s the temperatures array here. See that the result that returns back is divided by 7 in order to calculate the proper average temperature.

reduce accepts two arguments; the first one is the initial value that calculations will start with, and you can think of it like the initialization of the sum value above (sum = 0).

The second argument is a closure with two arguments as well. The first is the partial result of the calculations on each iteration, and the second is the value of the current item in the collection.

Instead of using actual arguments in the closure and have a return type, we can use the shorthand arguments instead, and shorten the above code. We do that like so:

The $0 argument is the partial result on each iteration, and the $1 is the current item in the temperatures array that is being added to the partial sum.

See that with a single line only we can achieve exactly what we achieved with five lines in the original implementation. But reduce can become even simpler when we have basic calculations, just like the one in this example. We can replace the closure containing the calculation formula with the symbol of the operation that we want to perform:

Amazingly simple, right?

We can use reduce with dictionaries as well, and pretty much the way we use them with arrays. Think of the temperatures again, but this time we have them as values next to day names into a dictionary:

Calculating the average temperature of the week is similar to what we already previously met with the $0 and $1 arguments. The only difference this time is that we need to explicitly access the value of the $1 argument, as the $1 is a tuple on its own, containing each key – value pair. In code:

That’s all about the reduce higher order function. It’s easy to use it, with the most important thing to take care of probably being the initial value that you will provide it with.

The contains higher order function

The contains higher order function helps to easily determine if the items of a collection satisfy a given condition or not, returning a Boolean value as a result.

contains is a really handy function, as quite often is necessary to give to the execution of a program a different path, depending on the results of some condition applied to the elements of a collection. To see how it works, suppose that the following array contains all languages that an app has been translated to:

Say now that we want to check if a certain language exists or not in the collection. For the sake of the example, let’s say that we’re looking for the existence of the German language. The condition in that case is to check if any of the array items is equal to the “German” value.

Let’s see first how we would be performing that check using a for-in loop:

Simple, yet too many lines for such a simple task. Let’s see now how we would perform the same with the contains function:

The closure of the function has one argument that represents each item in the original collection. Note that its return value is always a Boolean value. The closure’s body is the place to write the custom condition that we want to determine if any of the items satisfy.

As it happens with all higher order functions, contains has a shorter version as well:

Once again the $0 shorthand arguments comes to replace the explicit parameter name and make the whole syntax shorter and more clear. The only thing required between the curly brackets is the condition.

Let’s go through another example now, and for that we will use the dictionary with the temperatures from the previous part. Let’s assume that we want to check if there was at least one day with a temperature less than 10 degrees. With contains that’s as easy as shown next:

Or, we could check if there are days with temperature more than 17 degrees:

Note once again that all the above return a true or false value; not the actual items that satisfy the condition. If you want to get the actual items then you should use the filter higher order function.

The allSatisfy higher order function

A similar to contains is the allSatisfy higher order function. It works exactly just like the former one, returning a Boolean value as a result. However, there is a great difference; it returns true if only all items in the collection satisfy the given condition, otherwise it returns false. That’s contrary to contains, which returns true if at least one item in the collection satisfies the condition.

Let’s assume that the following array contains the grades of a student in five lessons as a percentage value (0 – 100):

The example scenario is to determine whether the student passes the base to all lessons, meaning that each grade is over 50%. We can use allSatisfy function to achieve that:

The closure’s argument matches to each grade on the original array while iterating through it. The return value, similarly to contains, is always a Boolean value, while the closure’s body is the place to write the condition.

The shorter version of the above is this:

allSatisfy is equally handy and useful to contains, just keep their difference in mind and use it when necessary.

The removeAll higher order function

The removeAll higher order function is quite useful when you want to remove items from a collection based on a given condition. It’s not meant to be used in order to remove elements at specific positions, as remove(at:) method does. Instead, its purpose is to remove only those elements that satisfy the condition.

There are two things to note about removeAll. The first is that it does not return a new collection, but it modifies the original one. Remember that if keeping the source collection is important to your program. The second is that removeAll is available for arrays only, not for dictionaries or sets.

To see how to use it, let’s consider the grades array from the previous part, but with one difference; we mark it with the var keyword so it can be mutated:

Let’s suppose that we want to remove all items that are less than 75, so we keep only those grades higher than that mark. Using the removeAll function in its expanded form we can do so like that:

Note that the condition should be satisfied by the items to remove, not those that should remain to the array.

Just like the last two higher order functions previously presented, the closure’s body is the place to write the custom condition. The above can be written even shorter:

Printing the grades array after the above will give us this:

As you can see, using the removeAll function is equally easy as the other higher order functions previously demonstrated. It’s a really useful tool that can save us from unnecessary coding when it’s necessary to perform tasks that match to its purpose.

Summary

In this post I presented and talked about another set of higher order functions in Swift. Like all other functions from the previous posts, those are great tools to know about and use, as they can lead to shorter, cleaner, and more readable and maintainable code. I hope you found valuable information to the content of this post today. Thank you for reading!

Stay Up To Date

Subscribe to my newsletter and get notifiied instantly when I post something new on SerialCoder.dev.

    We respect your privacy. Unsubscribe at any time.