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.

Pass function to another function:

Image for post
Image for post
higher order functions in swift

Return function from another function:

Image for post
Image for post

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]
var newArr: [Int] = []for value in arrayOfInt { newArr.append(value*10) }print(newArr) // prints [20, 30, 40, 50, 40, 70, 20]
Image for post
Image for post
maps on int array
let newArrUsingMap = arrayOfInt.map { $0 * 10 }
Image for post
Image for post
simplifying the map closure syntax

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]
Image for post
Image for post
map on dictionary
Image for post
Image for post
map on dictionary return values

Map on set:

Image for post
Image for post

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

Filter on array

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

Image for post
Image for post
filter using for-in loop
Image for post
Image for post
Image for post
Image for post
filter an int array
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.

let bookAmount = [“harrypotter”:100.0, “junglebook”:1000.0]
Image for post
Image for post
filter autocomplete on dictionary
Image for post
Image for post
let filteredArrayOnDict = bookAmount.filter { $1 > 100}

Filter on set

Image for post
Image for post
filter on set

Reduce

func reduce<Result>(_ initialResult: Result, _ nextPartialResult: (Result, Element) throws -> Result) rethrows -> Result
  • 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:

Image for post
Image for post
reduce method on arrays
  1. Initial value or Result is 1, x is 1, y is 2 → returns x+y . So, initial value or Result becomes 3 .
  2. Initial value or Result is 3, x is 3, y is 3→ returns x+y . So, initial value or Result becomes 6.
  3. Initial value or Result is 6, x is 6, y is 4→ returns x+y . So, initial value or Result becomes 10
let reducedNumberSum = numbers.reduce(0) { $0 + $1 }print(reducedNumberSum) // prints 10
Image for post
Image for post
reducing on int array
let reducedNumberSum = numbers.reduce(0,+) // returns 10
let reducedNumberSum = numbers.reduce(0) { $0 * $1 }
// reducedNumberSum is 0...
let reducedNumberSum = numbers.reduce(0,*)
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]
Image for post
Image for post
reducing dictionary
  1. A tuple of current key-value pair.
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.

Image for post
Image for post

Flatmap

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

Read it like : map + (Flat the collection)
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).
[“abc”,”def”,”ghi”].map { $0.uppercased() }
output: [“ABC”, “DEF”, “GHI”]
output: ["A", "B", "C", "D", "E", "F", "G", "H", "I"]
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.

Image for post
Image for post

I think, now it is clear what a flatMap 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:

Image for post
Image for post
flatmap to remove optionals.

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.

Image for post
Image for post
filtering while flatmap
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.

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-nil results of calling the given transformation with each element of this sequence.

Image for post
Image for post
Image for post
Image for post
compactmap on dictionary

Tip:

Image for post
Image for post

Conclusion

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

  • Enhances readability of code.
  • More functional programming.

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.

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