Creating a functional version of array filtering

The collections included in Swift allow us the use of higher order functions, that is, functions that take other functions and use them to perform transformations on datasets. For example, an array provides us with the filter, map, and reduce methods.

As previously explained, the preceding code represents an imperative version of array filtering. We can achieve the same goal with a functional approach using the filter method included in all the types that conform to the Sequence protocol. The Array<Element> struct conforms to the Sequence protocol and many other protocols. In Swift versions prior to 3, the Sequence protocol was named SequenceType.

Tip

As it happens in most modern languages, Swift supports closures, which are also known as anonymous functions. Closures are self-contained blocks of functionality that we can pass around and use within our code as functions without names. Closures automatically capture everything we reference, such as variables and functions that aren't defined within the closure. Closures in Swift are similar to blocks in Objective-C.

The following lines use a closure as an argument for the filter method to generate the array with the numbers divisible by 5. The closure is the code surrounded with braces ({}), and it uses the in keyword to separate the argument (number: Int) and the return type (Bool) for the closure from its body. The code file for the sample is included in the swift_3_oop_chapter_07_08 folder:

    var filteredNumbers = numbersList.filter({ 
      (number: Int) -> Bool in 
      return NumberFunctions.isDivisibleBy5(number: number) 
    }) 
    print(filteredNumbers)  

The code calls the filter method for the previously defined numbersList Array<Int>. This method creates and returns a new Array<Int> that contains only those elements of numbersList Array<Int> for which the Bool value returned by the specified closure returns true. In this case, the closure receives a number value of the Int type and returns the result of calling the NumberFunctions.isDivisibleBy5 type method with number as the number argument.

The following lines add a new filteredBy method to the existing NumbersWorker class. The method specifies a function type for the condition argument and then uses the function type within the closure that the filter method calls. This way, we are able to call this method with the function name that we want to receive an Int value and return Bool to evaluate which members of the original array are returned in the resulting array. The code file for the sample is included in the swift_3_oop_chapter_07_09 folder:

    open func filteredBy(condition: (Int) -> Bool) -> [Int] { 
      return numbersList.filter({
        (number: Int) -> Bool in
        return condition(number)
      })
    }

The next lines create a numbersList2 array of Int and then pass it as an argument to the initializer of the NumbersWorker class. The last line calls the worker2.applyFunctionToNumbers method with the NumberFunctions.isNumberDivisibleBy5 type method as an argument. The code file for the sample is included in the swift_3_oop_chapter_07_09 folder:

    var numbersList2 = [-30, -29, -47, 10, 30, 50, 80] 
    var worker2 = NumbersWorker(numbers: numbersList) 
    var filteredNumbers2 = worker2.filteredBy
    (condition: NumberFunctions.isDivisibleBy5) 
    print(filteredNumbers2)

The following screenshot shows the results of executing the previous lines in the Playground:

Creating a functional version of array filtering

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.22.61.179