Higher Order Functions in Swift – forEach, filter, sorted

April 15th, 2021

⏱ Reading Time: 7 mins

Welcome to the third part of the series about higher order functions in Swift! In the first part I went through a general presentation of what a higher order function is, and how you can create your own. In the second post I focused on three related higher order functions; map, compactMap, flatMap. This post keeps going with the presentation of the most important and most used higher order functions in Swift; here you will find out about forEach, filter and sorted functions.

The forEach higher order function

forEach higher order function can be used in place of for-in loops in order to iterate through the elements of a collection. Unlike most of the other higher order functions, forEach does not return a new collection; instead it just goes through the original collection and allows to use its items in repetitive operations and tasks.

Let’s see a really simple example. Consider the following array with positive and negative numbers:

Let’s suppose that we want to go through the array and print the absolute value of each number. We can do that in a for-in loop like that:

That traditional way can be replaced by the forEach higher order function. All we have to do is to access it through the numbers array:

The argument in the above closure represents each item in the source collection while performing the loop. Most of the times we can omit it and use the shorthand argument instead:

All the above snippets will print exactly the same result.

Of course, it’s also possible to apply custom logic and conditions in the closure’s body of the forEach. For instance, the following code prints all positive numbers in the original array:

There is something that we cannot do using forEach. That is, to act on the original items while iterating through them. If you want to use a higher order function in order to update the original collection, then you should consider using map, but not forEach; the latter aims to provide us with each item inside a loop, keeping the source collection immutable.

To understand that, see the next snippet:

All it does is to double the value of each number in the numbers array. Even though the above will perfectly do the job, the following won’t work:

Trying to do so will make Xcode show the following error:

Left side of mutating operator isn't mutable: '$0' is immutable

Keep that in mind, and don’t try to update elements in the original collection using a forEach.

Dictionaries, as well sets, can also be used with forEach, as they are collection types as well. To see an example, let’s consider the following dictionary that keeps a few European countries and their capital cities:

We can use forEach to print each key-value pair separately like so:

Each loop prints a tuple containing both the key and the actual value:

It’s also possible to access the keys, or the values only:

So, this is the forEach higher order function in a nutshell. Use it instead of the traditional loops when possible, as it helps to write shorter and cleaner code.

The filter higher order function

The name of the filter higher order function pretty much explains its purpose. When applied to a collection, it returns another one after having filtered original elements based on a condition.

Let’s consider once again the example numbers array from the previous part, and let’s suppose that we want to get only the negative numbers using the filter method. In the most expanded form, this can be done as follows:

The return type of the closure is a Bool value; items in the resulting array are those that satisfy the condition inside the body; in this case, numbers lower than zero. The number argument of the closure represents each item in the original collection.

As it happens with other higher order functions, we can omit explicitly setting the return type, as well as the return keyword if it’s a single-line statement in the closure. That means that we can write the above simpler as so:

It can become even simpler if we use the shorthand argument and write everything in one line only:

All the above are equal, however the last snippet is the most clear and shortest way to filter the original numbers.

In the same logic, we can also get all numbers that are higher than 10:

filter, like any other higher function, is not limited in collections whose items are of basic data types. It can be used when items are of custom types as well. Consider the following structure that describes a member of a club:

Let’s say that we have the following members:

Let’s see a few scenarios and examples. To start, let’s suppose that we want to filter the above and get male members only. We do that with the expanded form of filter as shown right next:

Or, we can do even better with its shorter version:

Just a single line of code returns a new array that contains only those elements that satisfy the condition inside the closure. See that we can access a property of the custom type through the shorthand argument, exactly as if we had a normal object; $0 is the object in this case.

To continue with another example, the following returns all female members that are in their 30s:

And the next one all male members under 30:

Generally, we can write any possible condition in the closure that is valid in the context. As an example of that, the following filters all members and returns only those where their names starts with “S”:

In order to quickly print and see the contents of each resulting array we can use the forEach higher order function presented earlier. This is what exactly is happening next regarding the last array above:

Sean
Susan

There is nothing particularly difficult regarding the filter higher order function. The only thing you should take great care about is the conditions you apply in it, so it returns back the correct and expected results.

The sorted higher order function

The sorted higher order function can be used in order to sort a collection in ascending or descending order. What it returns back is a new collection with the items sorted.

To see an example, consider once again the numbers array presented in the first part of this post. Supposing that we want to sort it in ascending order and go from the lowest to the highest value, sorted can be used like so:

The two arguments in the closure are the two items that are being compared at any given moment during sorting. Comparison is determined as a condition in the closure’s body.

Similarly to all other higher order functions, arguments, return type, as well as the return keyword can be omitted and use shorthand arguments instead:

That’s much shorter than the previous snippet, and see that the second element is represented with the $1 shorthand argument.

sorted gives us a faster option to perform the comparison as well; to indicate the order only, without using any arguments at all:

Besides sorted, there is also the sort higher order function. Even though its purpose is to place the items of a collection in ascending or descending order too, there is a great difference between the two; sorted returns a new array with the sorted items, while sort sorts items in the original collection.

The following code sorts all numbers in the numbers array in descending order, but it does not return a new array; changes happen in place on the same array:

The above results to:

As an advice, do not use sort if you want to have the original collection intact after sorting. On the other hand, do not use sorted if you have a really big collection to sort; that would require much additional memory, so it would be better to use sort in order to sort in place.

One last useful piece of information you should be aware about, is what sorted returns when applied to dictionaries. Let’s use as example the dictionary with the few countries and capitals presented in the first part of this post:

To sort it based on the city names from A to Z we can do the following:

The interesting part is here; what sorted returns is not a new dictionary, but an array of tuples containing all key-value pairs ordered. The above code results to this:

Summary

Today I presented three quite common higher order functions in Swift that are great tools in programming; forEach, filter and sorted. When they are used in place of traditional solutions implemented using loops, code can become much shorter, cleaner, readable and maintainable. As a reminder, this is the third post in the series of higher order functions in Swift. You can find a general introduction in the first post, and a discussion about map, compactMap and flatMap in the second post. More higher order functions will be presented in the next article. Until then, take care and thanks 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.