Higher order functions in Swift: Filter, Map, Reduce, flatmap, compactMap

Ever since I learned about functions and closures in detail, I wanted to know more about the advantages and usages of these in programming. I read about higher order functions that can be used on collection types and this is what I understood.

Image for post
Image for post
I don’t know who that is over there at the top.

As far as I understood, higher order functions are functions that takes another function/closure as argument and returns it.

I will try to explain this first. Consider the following code which will give you an idea what a higher order function is :

Pass function to another function:

Image for post
Image for post
higher order functions in swift

The first two methods are of type . First one accepts two values and return their sum . The second one returns the product of these two values. The third method is a higher order function which accepts three parameters. Two values and a function of type . Do have a look at the method call. You will understand how a higher order function works.

Return function from another function:

Image for post
Image for post

Here , the function is a higher order function which returns a function of type .

Functions and closures are first class members in swift. They can be saved into a variable and passed around.

So, here , based on the bool value passed into the function, it returns the function which does the operation.

is a function that does the multiplication for you.

is a function that does the addition for you.

Just have a look at the function definition and call. You will understand everything.

Of course, you can do the same stuff in plenty of different ways. May be you could use a closure instead of functions. You could create an enum of arithmetic operations and simplify the function. I just meant to explain what s higher order function is .

Here are some of the higher order function used in swift. If I understood correctly, the following functions uses closures as argument . You can use these functions to operate on Swift collection types such as or .

You should understand what a closure is before going through the following. Read my article on closures

Map

Use to loop over a collection and apply the same operation to each element in the collection. The function returns an array containing the results of applying a mapping or transform function to each item.

Map on array:

Suppose we have an array of integers:

What if we have to multiply every number by ? We normally use a loop to iterate through every number and do the operation right?

This code looks verbose. There are some boilerplate code like creating a new array, which could be avoided using . The swift autocomplete shows the following if we try to map the array.

Image for post
Image for post
maps on int array

The closure accepts an argument and returns a generic type.

This is the shortest version of using on an array of . I used the shorthand syntax of using $ operator.

All the following code will work the same as above , but a complex to simplified syntax. You should have a good knowledge in to do that.

Image for post
Image for post
simplifying the map closure syntax

Working of map: The function has a single argument which is a closure (a function) that it calls as it loops over the collection. This closure takes the element from the collection as an argument and returns a result. The map function returns these results in an array.

Map on Dictionary:

Consider a dictionary with book names as key and the amount of each book as the value.

If you try to do a map function on a dictionary, the swift autocomplete will look like this:

Image for post
Image for post
map on dictionary

Here, for the above dictionary, as we iterate over the collection our closure has arguments that are a and a from the types of the key and value that make up each element of the dictionary. The return type can be an array of uppercased keys, values array with discounts or even an array of tuples. It’s all upto you.

Image for post
Image for post
map on dictionary return values

Note: The return type of a map function is always a generic array. You can return an array of any type.

Map on set:

Image for post
Image for post

In this case we have a set containing elements of type so our closure also expects a . is a set. is an array.

What if you want to know the index of the collection while applying map to it??

Answer is simple. You will have to enumerate it before mapping.

Image for post
Image for post

Check the code below.

Filter

Use to loop over a collection and return an containing only those elements that match an include condition.

Filter on array

Consider the following code to filter even numbers from an array of .

Image for post
Image for post
filter using for-in loop

Now, like , there is a simple method to do the filtering stuff for collection types.

The swift autocomplete shows the following if we try to use method for an array.

Image for post
Image for post

As you can see, the filter function calls a closure called which takes one as argument and returns a . So, the closure will return a value for each collection item and based on this result a new filtered array will be generated.

The method has a single argument that specifies the include condition. This is a closure that takes as an argument the element from the collection and must return a indicating if the item should be included in the result.

Image for post
Image for post
filter an int array

The filter closure can be further simplified like we did for map.

Image for post
Image for post
Simplified filter closure on Int array

Filter on dictionary

Consider a dictionary with book names as key and the amount of each book as the value.

If you try to do a filter function on a dictionary, the swift autocomplete will look like this:

Image for post
Image for post
filter autocomplete on dictionary

The filter functions will call a closure called by passing each key-value pair and do the condition check (here, it accepts a and as arguments). Finally, based on the bool value returned, the filter function will decide whether or not to add the key-value pair in the returned array.

Important: Filter function on dictionary returns an array of Tuples as you can see in the playground code below:

Image for post
Image for post

This can be further simplified as:

$0 is the key, $1 is the value

Filter on set

Image for post
Image for post
filter on set

Here, the filter closure for set takes a argument and returns a for each element in the set. Based on this value, the item is included in the filtered array.

IMPORTANT: The return type is a filtered array.

Reduce

Use to combine all items in a collection to create a single new value.

Declaration as in apple docs:

So, the function takes two arguments.

  • One is an which is used to store the initial value or the or returned by the closure from each iteration.
  • The other one is a closure which takes two arguments, one is the or the from the previous execution of the closure and the other one is the in the .

Reduce on arrays

Let’s understand this with an example:

Check the following array of numbers.

Image for post
Image for post
reduce method on arrays

This function will iterate four times.

  1. Initial value is 0, x is 0, y is 1 → returns x+y . So, initial value or Result becomes 1.
  2. Initial value or Result is 1, x is 1, y is 2 → returns x+y . So, initial value or Result becomes 3 .
  3. Initial value or Result is 3, x is 3, y is 3→ returns x+y . So, initial value or Result becomes 6.
  4. Initial value or Result is 6, x is 6, y is 4→ returns x+y . So, initial value or Result becomes 10

The reduce function can also be simplified like:

Image for post
Image for post
reducing on int array

Here the closure is of type . So, we can pass any function or closure of type . In this scenario, instead of the closure, we could also pass basic operator functions like +, -, *, / .

We can also use multiplication or other operation or logic inside the closure.

the above line can also be written as:

will also work with strings using the operator to concatenate:

Reduce on dictionary

Let’s reduce the bookAmount Dictionary:

Image for post
Image for post
reducing dictionary

For dictionary, the closure inside the reduce function takes two arguments.

  1. An initial or result value of the type that should be reduced to.
  2. A tuple of current key-value pair.

The can be further simplified using the short closure syntax like:

Reduce on set

The reduce on set works the same way as in arrays.

Image for post
Image for post

Return type is the return type of closure. Here it is .

Flatmap

Flatmap is used to flatten a collection of collections . But before flattening the collection, we can apply map to each elements.

Apple docs says: Returns an array containing the concatenated results of calling the given transformation with each element of this sequence.

Image for post
Image for post
(fig — 1) Read the above definition and have a look at this code.
Image for post
Image for post
(fig — 2)… and this (string is a collection from swift 4).

In the (fig — 2) above, the flatMap iterates through all the collections in the collection called codes. Here, the individual collections are string (string is a collection from swift 4). Here are the steps:

1 . Apply function to all strings. This is similar to

Output will be:

2 . Flatten all the sub — collections to one single collection.

Image for post
Image for post
Finally, this is what flatMap does to a string

Tip:

In swift 3, flatmap was also used for removing nil values from a collection. This is deprecated now and the complier will throw a warning when used.

We should use compactMap instead. Explained later in this article.

Image for post
Image for post

I think, now it is clear what a does.

Flatmap on array

Image for post
Image for post
flatmap of array of array of int

Flatmap on array of dictionaries

It returns an array of tuples after flatmapping. We have to convert it to an array:

Image for post
Image for post
flatmap an array of dictionaries

Flatmap on set

Image for post
Image for post
flatmap on set

Advantages of flatmap:

Let’s dig into the advantages of flatmap:

Removing optionals:

Even more usefully it knows about optionals and will remove them from a collection.

Image for post
Image for post
flatmap to remove optionals.

Flatmap by filtering or mapping

We can apply on of . ie; an of will be flattened to a single array. So, the takes a single collection of argument, do something with this collection and /or return the collection. Here , before returning the collection, we can apply or or even reduce.

Image for post
Image for post
filtering while flatmap

When applying the short closure syntax:

Chaining : (map + filter + reduce)

We can chain multiple higher order functions one by one.

You can read my article on chaining methods to understand its working.

The working principle behind the chaining is simple. The and methods act on a collection and returns another collection . And now, we can again apply another higher order function on this collection. It’s that simple.

Let’s say we want to add the squares of all the even numbers from an array of arrays.

Image for post
Image for post
add the squares of all the even numbers from an array of arrays.

CompactMap

Returns an array containing the non- results of calling the given transformation with each element of this sequence.

Image for post
Image for post

If you do compactmap a collection containing optional values, it will only consider the values. This doesn’t do anything on sets and dictionaries as Sets cannot have nil values and for dictionary, the compactmap will give an array of tuples with key and value.

Note: In swift 5, is introduced which adds functionality to dictionary as well. Will update the article soon.

Image for post
Image for post
compactmap on dictionary

Tip:

Image for post
Image for post

The output of map became a collection of optional int only because the array had in it. Otherwise it would have been an array.

Conclusion

Well, thats it!! You mastered Higher order functions!!

Use Higher order functions where ever possible:

  • It improves your swift skills.
  • Enhances readability of code.
  • More functional programming.

Our objective is to write less code which makes more sense!!!

Enjoy!!

Reference: Link1

If you enjoyed reading this post, please share and give some clapps so others can find it 👏👏👏👏👏 !!!!

You can follow me on Medium for fresh articles. Also, connect with me on LinkedIn and Twitter.

If you have any comment, question, or recommendation, feel free to post them in the comment section below!

Written by

iOS and tvOS developer, dreamer, photographer 🤨

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store