As far as I understood, higher order functions are functions that takes another function/closure as argument and/or returns it.
Higher order functions are simply functions that operate on other functions by either taking a function as an argument, or returning a function. Swift’s Array type has a few methods that are higher order functions: sorted, map, filter, and reduce. 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.
If you look around the internets the most commonly mentioned higher order functions in Swift are generally map, filter, reduce and sort (or sorted). But there are so many more to play with!
Just take a look at Array – you will also find contains, drop, first, flatMap, forEach, partition and split.
Map
Use map
to loop over a collection and apply the same operation to each element in the collection.
Map on array:
Let’s assume we need to multiply each item by 10 in an array called numberArray
let numberArray = [2,3,4,5,6,7,8]
let emptyArray:[Int] = []
//MARK:-Traditional Way
for number in numberArray{
emptyArray.append(number*10)
}
//MARK:-Higher Order Functions that is map
There are few form’s: long-form vs shorthand closure syntax preference.
//1) Way
emptyArray = []
emptyArray = numberArray.map ( { (value:Int) -> Int in
return value*10
})
//2) Way
emptyArray = []
emptyArray = numberArray.map( { (value:Int) in
return value*10
})
//3) Way
emptyArray = []
emptyArray = numberArray.map {value in value*10}
//4) Way
emptyArray = []
emptyArray = numberArray.map {$0 * 10}
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:
let reviews = [“likes”:50, “comments”:52]
Here, for the above dictionary, as we iterate over the collection our closure has arguments that are a String
and a Int
from the types of the key and value that make up each element of the dictionary. The return type can be an array of values (i.e., 50), values array with discounts or even an array of tuples. It’s all upto you.
let reviewsCount = reviews.map { (key, value) in
return value
}
print(reviewsCount)
//[50, 52]
Map on Custom Object:
struct Person{ let name:String let id:Int init(name:String, id:Int){ self.name = name self.id = id } } let personDict = ["Palash":1,"Rahul":2,"Govind":3] let persons = personDict.map{ name, id in Person(name: name, id: id)} print(persons.first?.name) //Palash Array count Traditional Way Exe. time Using Hight Order Function map Exe. time 6930 0.0645290017127991 0.00439298152923584
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.
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. I have given the shorthand closure syntax example below.,
//MARK:-Traditional Way
emptyArray = []
for no in numberArray{
if no % 2 == 0{
emptyArray.append(no)
}
}
//MARK:-Higher Order Functions
emptyArray = []
emptyArray = numberArray.filter{$0 % 2 == 0}
Filter on dictionary:
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.
Filter function on dictionary returns an array of Tuples .
let reviewsFilter = reviews.filter { (key, value) in
return value > 50
}
print(reviewsFilter)
//52
This can be further simplified as:
let reviewsFilter1 = reviews.filter { $1 > 50}
Note: $0 is the key, $1 is the value
Array count Traditional Way Exe. time Using Hight Order Function map Exe. time
3300 0.000292956829071045 0.00520197877883911
Reduce
Combines all items in a collection to create a single value.
The most versatile function reviewed here is reduce. Reducing a sequence means transforming many items into a single item. For example, an array of integers could be reduced to the sum of every integer in the array. In this case, a sequence of integers is reduced to a single integer.
//MARK:-Traditional Way
var sum = 0
for no in numberArray{
sum += no
}
The two parameters in reduce function are a starting value and a function respectively. The function takes a running total and an element of the array as parameters, and returns a new running total.
//MARK:-Higher Order Functions
//1 Way
var sum = numberArray.reduce(0, {$0 + $1})
//2 Way
var sum = numberArray.reduce(0,+)
In above scenario, instead of the closure, we could also pass basic operator functions like +, -, *, / . So we can say reduce
is used to combine all items in a collection to create a single new value.
Reduce on dictionary
let totalReviews = reviews.reduce(0) { (result, tupleOfKeyAndValue) in
return result + tupleOfKeyAndValue.value
}
Flatmap
When implemented on sequences : Flattens a collection of collections.
There are two versions of this function: one that supports mapping optional values and another that supports mapping a sequence of sequences, such as [[Int]] (i.e. an array of array of integers)
let tempArray = _flatMap([“Hi”,” “,“there”,” “, nil,“?!!!!”]) { $0 }
print(tempArray)
//Hi there ?!!!!
This function is like a mixture of map and filter. It creates a sequence of mapped values, but a mapped value is not added to the output sequence when the closure returns nil. In that sense, returning nil is similar to returning false from a closure passed to the filter function.
Happy Coding… ???
I will show the usage of remaining higher order function in my next post.