Higher Order functions in Swift

ANKIT BANSAL
5 min readAug 19, 2021

--

In mathematics and computer science, a higher-order function is a function that does at least one of the following:

– takes one or more functions as arguments (i.e. procedural parameters),

– returns a function as its result. -Wikipedia

Higher order functions are based on closures. These methods use closures to allow us to pass in functionality that can then determine how we want the method to sort, map, filter, or reduce an array of objects.

In this tutorial we will discuss about most commonly used higher order functions in Swift that are listed below:

  • Map
  • CompactMap
  • FlatMap
  • Filter
  • Reduce
  • ForEach
  • Contains
  • RemoveAll
  • Sorted
  • Split

In order to explain I’ll show you some of the examples of each of these methods and talk a little bit about how the syntax of the closure can change based on what swift can infer.

Map

Let’s get started with Map. This function performs an operation on all the elements of a collection and returns a new collection with the results of the operation on the original elements.

let digits= [2, 5, 3, 9, 15, 12, 8, 17, 20, 11]

let doubled = digits({ (digit) -> Int in

return digit * 2

})

Shorthand argument:

let doubled = digits.map { $0 * 2 }

We can use Map with Dictionary and Sets too.

var data = [String: String]()

data[“name”] = “John”

data[“place”] = “Austin”

data[“job”] = “QA”

data[“interest”] = “Singing”

let keys = data.map { $0.key } //Array of all keys

let values = data.map { $0.value } // Array of all values

let result = info.map { $0 } // Array of key and value pair

Compact Map

The major difference between map and compact map is the resulting array does not contain any nil values.

let digitsWithNil = [5, 15, nil, 3, 9, 12, nil, nil, 17, nil]

let notNilDoubled = digitsWithNil.compactMap { $0 != nil ? $0! * 2 : nil }

// Prints [10, 30, 6, 18, 24, 34]

Flat Map

It is useful when there are collections inside collections, and we want to merge them into one single collection.

let marks = [[3, 4, 5], [2, 5, 3], [1, 2, 2], [5, 5, 4], [3, 5, 3]]

let allMarks = marks.flatMap { (array) -> [Int] in

return array

}

Shorthand argument:

let allMarks = marks.flatMap { $0 }

// Prints [3, 4, 5, 2, 5, 3, 1, 2, 2, 5, 5, 4, 3, 5, 3]

If null values are available in the collection it will not remove and add null values as well.

Filter

Its purpose is to filter the elements of a collection based on a condition and produce a new one containing only those elements that satisfy the condition.

let digits = [2, 5, 3, 9, 15, 12, 8, 17, 20, 11]

let over10 = digits.filter { (digit) -> Bool in

return digit > 10

}

Shorthand argument:

let over10 = numbers.filter { $0 > 10 }

//Prints [15, 12, 17, 20, 11]

Reduce

The reduce function allows you to combine all the elements in an array and return an object of any type.

Notice that reduce has two parameters — initialResult and nextPartialResult. We need the initial result to tell us where to start, and the method then operates on that result based on the logic in the closure.

let digits = [5, 3, 8, 4, 2]

let product = digits.reduce(0, { $0 + $1 })

//Prints 22

For Each

Like all the other higher order functions, it provides a closure that implements the custom logic. But this time we’ll use the for Each function instead of using for-in :

let digits = [2, 5, 3, 9, 15]

digits.forEach { $0.isMultiple(of: 2) ? print(“\($0) is even”) : print(“\($0) is odd”) }

// Prints

2 is even

5 is odd

3 is odd

9 is odd

15 is odd

Contains

This function is used in collections in order to check if there are elements that satisfy a certain condition and it returns a boolean value.

let digits = [2, 5, 3, 9, 15]

let hasNumbersLessThan5 = digits.contains { $0 < 5 }

//Prints True

Remove All

Similar to contains is the removeAll method which is pretty handy when it’s necessary to remove collection elements based on conditions that regard the actual element values.

var digits = [2, 5, 3, 9, 15, 12, 8, 17, 20, 11]

numbers.removeAll { $0 < 10 }

//Prints [15, 12, 17, 20, 11]

Sorted

When sorting order must be specified (ascending or descending), or sorting should be based on a specific condition, then this is where sorted higher order function gets into play.

let digits = [5, 3, 8, 2, 10]

let sorted = digits.sorted { $0 > $1 }

Even more shorthand argument:

let sorted = toSort.sorted(by: >)

//Prints [10,8,5,3,2]

Split

This function is used with String values and its purpose is to split a string into pieces based on a given condition. The result is an array of substrings. It works pretty similar to components(separatedBy:) that breaks a string based on a given separator. Note though that in split only characters can be provided as separators. You might wonder why this function applies on String values given that strings are not collections. The truth is that split is used in the sequence of characters in the string, which conforms to the Collection protocol.

Two more things to note. First, the type of the elements in the array that split creates is String.SubSequence, not String. If you want to use them as strings, you must create string objects with them first. The following example creates a new array where all substrings are being converted to strings using the map function:

let message = “Hello World!”

let result = message.split { $0 == “ “ }

print(result)

// Prints [“Hello”, “World!”]

// result type is [String.SubSequence]

// Create String values from substrings.

let allStrings = result.map { String($0) }

print(allStrings)

// Prints [“Hello”, “World!”]

// allStrings type is [String]

Reference: https://www.appcoda.com/higher-order-functions-swift/

--

--

ANKIT BANSAL

I devise, design and develop well-crafted interactive iOS and Android apps. Cocoa & Swift adventures. Working @Accenture Ex. @thinkfuturetech