Combining map with reduce

The following lines show an imperative code version of a for in loop that calculates the sum of all the highestScore values for the games. The code file for the sample is included in the swift_3_oop_chapter_07_26 folder:

    var sum = 0 
    for game in gameRepository.getAll() { 
      sum += game.highestScore 
    } 
    print(sum) 

The code is very easy to understand. The sum variable has a starting value of 0, and each iteration of the for in loop retrieves a Game instance from the Array<Game> returned by the gameRepository.getAll method and increases the value of the sum variable with the value of the highestScore property.

We can combine the map and reduce operations to create a functional version of the previous imperative code to calculate the sum of all the highestScore values for the games. The next lines chain a call to map to a call to reduce to achieve this goal. Take a look at the following code. The code file for the sample is included in the swift_3_oop_chapter_07_27 folder:

    let highestScoreSum = gameRepository.getAll().map({ $0.highestScore 
    }).reduce(0, { 
      sum, highestScore in 
      return sum + highestScore 
    }) 
    print(highestScoreSum) 

First, the code uses the call to map to transform an Array<Game> into an Array<Int> with the values specified in the highestScore stored property. Then, the code calls the reduce method that receives two arguments that do not use parameter labels: the initial value for an accumulated value and a combine closure that will be repeatedly called with the accumulated value. The method returns the results of the repeated calls to the combine closure.

Tip

In Swift versions prior to 3, it was necessary to use the combine parameter label for the second argument in the call to the reduce method. If we specify the combine parameter label for the second argument in Swift 3, the code won't compile.

The closure specified in the second argument for the reduce method receives sum and highestScore and returns the sum of both values. Thus, the closure returns the sum of the total accumulated so far plus the highestScore value that is processed. We can add a print statement to display the values for both sum and highestScore within the closure specified in the second argument. The following lines show a new version of the previous code that adds the line with the print statement. The code file for the sample is included in the swift_3_oop_chapter_07_28 folder:

    let highestScoreSum2 = gameRepository.getAll().map({ 
    $0.highestScore }).reduce(0, { 
      sum, highestScore in 
      print("sum value: (sum), highestScore value: (highestScore)") 
      return sum + highestScore 
    }) 
    print(highestScoreSum2) 

The following lines show the results for the previous line, where we can see how the sum value starts with the initial value specified in the initial argument for the reduce method and accumulates the sum completed so far. Finally, the highestScoreSum2 variable holds the sum of all the highestScore values, that is, the last value of sum, 85,912,770 plus the last highestScore value, 10,572,340. The result is 96,485,110:

sum value: 0, highestScore value: 1050
sum value: 1050, highestScore value: 3741050
sum value: 3742100, highestScore value: 67881050
sum value: 71623150, highestScore value: 10025
sum value: 71633175, highestScore value: 1450708
sum value: 73083883, highestScore value: 1050320
sum value: 74134203, highestScore value: 6705203
sum value: 80839406, highestScore value: 4023134
sum value: 84862540, highestScore value: 1050230
sum value: 85912770, highestScore value: 10572340
96485110

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

Combining map with reduce

In the previous code, we had to pass a closure expression to the reduce method as the method's final argument, and the closure expression is long. We can write it as a trailing closure, that is, a closure expression written after the closing parenthesis of the method call and outside it. The following lines show a new version of the previous code that uses a trailing closure. Note that the call to reduce seems to include just one argument: 0. However, the code included within curly braces after the method call is the combine argument for reduce. Take a look at the following lines. The code file for the sample is included in the swift_3_oop_chapter_07_29 folder:

    let highestScoreSum3 = gameRepository.getAll().map({ 
    $0.highestScore }).reduce(0) { 
      sum, highestScore in 
      print("sum value: (sum), highestScore value: (highestScore)") 
      return sum + highestScore 
    } 
..................Content has been hidden....................

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