Higher order functions in swift

H

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 mapfilter, reduce and sort (or sorted). But there are so many more to play with!

Just take a look at Array – you will also find containsdropfirstflatMapforEachpartition  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 Doubleas 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.

About the author

Shashikant Bhadke
By Shashikant Bhadke

Category