# 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. 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:

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

## Return function from another function:

Here , the function `doArithmeticOperation(isMultiply:)` is a higher order function which returns a function of type `(Double,Double)->Double` .

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 `doArithmeticOperation(isMultiply:) `function, it returns the function which does the operation.

`operationToPerform_1` is a function that does the multiplication for you.

`operationToPerform_2` 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 `Array, set`or `Dictionary` .

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

# Map

Use `map` to loop over a collection and apply the same operation to each element in the collection. The `map` 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:

`let arrayOfInt = [2,3,4,5,4,7,2]`

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

`var newArr: [Int] = []for value in arrayOfInt { newArr.append(value*10) }print(newArr) // prints [20, 30, 40, 50, 40, 70, 20]`

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

The closure `transform` accepts an `int` argument and returns a generic type.

`let newArrUsingMap = arrayOfInt.map { \$0 * 10 }`

This is the shortest version of using `map` on an array of `Int`. I used the shorthand syntax of `closures` 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 `closures` to do that.

Working of map: The `map` 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.

`let bookAmount = [“harrypotter”:100.0, “junglebook”:100.0]`

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

Here, for the above dictionary, as we iterate over the collection our closure has arguments that are a `String` and a `Double` 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.

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

## Map on set:

In this case we have a set containing elements of type `Double` so our closure also expects a `Double`. `lengthInMeters` is a set. `lengthInFeet` 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.

Check the code below.

`let numbers = [1, 2, 4, 5]let indexAndNum = numbers.enumerated().map { (index,element) inreturn "\(index):\(element)"}print(indexAndNum) // [“0:1”, “1:2”, “2:4”, “3:5”]`

# Filter

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

## Filter on array

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

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

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

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

The `filter` 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 `Bool` indicating if the item should be included in the result.

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

## Filter on dictionary

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

`let bookAmount = [“harrypotter”:100.0, “junglebook”:1000.0]`

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

The filter functions will call a closure called `isIncluded` by passing each key-value pair and do the condition check (here, it accepts a `String` and `Double` 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:

This can be further simplified as:

`let filteredArrayOnDict = bookAmount.filter { \$1 > 100}`

\$0 is the key, \$1 is the value

## Filter on set

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

IMPORTANT: The return type is a filtered array.

# Reduce

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

Declaration as in apple docs:

`func reduce<Result>(_ initialResult: Result, _ nextPartialResult: (Result, Element) throws -> Result) rethrows -> Result`

So, the `reduce` function takes two arguments.

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

## Reduce on arrays

Let’s understand this with an example:

Check the following array of numbers.

This `reduce` 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:

`let reducedNumberSum = numbers.reduce(0) { \$0 + \$1 }print(reducedNumberSum) // prints 10`

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

`let reducedNumberSum = numbers.reduce(0,+) // returns 10`

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

`let reducedNumberSum = numbers.reduce(0) { \$0 * \$1 }// reducedNumberSum is 0...`

the above line can also be written as:

`let reducedNumberSum = numbers.reduce(0,*)`

`Reduce` will also work with strings using the `+` operator to concatenate:

`let codes = ["abc","def","ghi"]let text = codes.reduce("") { \$0 + \$1} //the result is "abcdefghi"orlet text = codes.reduce("",+) //the result is "abcdefghi"`

## Reduce on dictionary

Let’s reduce the bookAmount Dictionary:

`let bookAmount = [“harrypotter”:100.0, “junglebook”:1000.0]`

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 `reducedBookNamesOnDict2` can be further simplified using the short closure syntax like:

`let reducedBookNamesOnDict = bookAmount.reduce(“Books are “) { \$0 + \$1.key + “” } //or \$0 + \$1.0 + “”`

## Reduce on set

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

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

# 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.

`Read it like : map + (Flat the collection)`

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 `upperCased() `function to all strings. This is similar to

`[“abc”,”def”,”ghi”].map { \$0.uppercased() }`

Output will be:

`output: [“ABC”, “DEF”, “GHI”]`

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

`output: ["A", "B", "C", "D", "E", "F", "G", "H", "I"]`

# 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.

I think, now it is clear what a `flatMap` does.

## Flatmap on array of dictionaries

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

## Flatmap on set

Let’s dig into the advantages of flatmap:

## Removing optionals:

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

## Flatmap by filtering or mapping

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

When applying the short closure syntax:

`let onlyEven = collections.flatMap { \$0.filter { \$0 % 2 == 0 } }`

# 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 `map` and `filter` 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.

# CompactMap

If you do compactmap a collection containing optional values, it will only consider the `non-nil `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, `compactMapValues()` is introduced which adds functionality to dictionary as well. Will update the article soon.

## Tip:

The output of map became a collection of optional int `([Int?])` only because the array had `nil — value` in it. Otherwise it would have been an `Int` array.

# Conclusion

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

Use Higher order functions where ever possible:

• It improves your swift skills.