A preliminary study of higher order functions

In Swift, higher-order functions are as follows:

  • Map: Performs a mapping in the closure for each element of a given array, returns the result of the mapping placed in the array.
  • FlatMap: For each element of a given array, the mapping in the closure is performed on the result of the mappingMerge operation,The result of the merge operation is then returned in an array.
  • CompactMap: For each element of a given array, perform the mapping in the closure, willnon-emptyMapping results placed in an array are returned.
  • CompactMap performs the mapping in the closure for each element of the given array, which willnon-emptyMapping result – key value pair placed in dictionary returns.
  • Filter: Performs the operation in the closure for each element of the given array, and willQualifying elementsPut it in an array.
  • Reduce: For each element of a given array, perform the operations in the closure on the elementsmergeAnd returns the result of the merge.

Now that we have a general idea of what these functions do, let’s look at some examples of how to use them in code.

map

For the map function, the use scenario is to map the type of the array to another type. For example, if we have an array of models, and the id field of the model is a String from the server, we need to convert it to an Int in certain scenarios, and we can use the map function to do that.


struct Student {
    let id: String
    let name: String
    let age: Int
}
 
let stu1 = Student(id: "1001", name: "stu1", age: 12)
let stu2 = Student(id: "1002", name: "stu2", age: 14)
let stu3 = Student(id: "1003", name: "stu3", age: 16)
let stu4 = Student(id: "1004", name: "stu4", age: 20)
let stus = [stu1, stu2, stu3, stu4]
 
let intIds = stus.map { (stu) in
    Int(stu.id)
}
 
print(intIds) //[Optional(1001), Optional(1002), Optional(1003), Optional(1004)]
Copy the code

With the code above, we map the ID field from String to Int? Type, that’s not what we want for an Int. If we need to access elements and we need to unpack them, how do we map elements and automatically filter nil values? At this point, it’s compactMap’s turn.

compactMap

Let’s replace the above code with:

 let intIds = stus.compactMap { (stu) in
     Int(stu.id)
   }
Copy the code

If we print intIds, we’ll see that it’s already an Int.

compactMapValues

For sets and arrays, you can use compactMap to get non-empty collections, but for dictionaries, this function does not work.

let dict = ["key1": 10, "key2": nil]
let result = dict.compactMap { $0 }
print(result) //[(key: "key1", value: Optional(10)), (key: "key2", value: nil)]
Copy the code

At this point, we need to use the compactMapValues function to get the non-empty dictionary.

  print(result) //["key1": 10]
 let result = dict.compactMapValues { $0 }
 print(result) //["key1": 10]

Copy the code

flatMap

For flatMaps, the main application scenario is that you want to get an array of single-layer collections. Use the following code to see the difference between map and flapMap.

  let scoresByName = ["Henk": [0, 5, 8], "John": [2, 5, 8]]

  let mapped = scoresByName.map { $0.value }
  // [[2, 5, 8], [0, 5, 8]]
  print(mapped)

 let flatMapped = scoresByName.flatMap { $0.value }
  // [2, 5, 8, 0, 5, 8]
Copy the code

A map places elements directly in an array, while a flatMap tils elements in an array. Actually, s.latmap (transform) is the same as s.map.transform (transform).joined().

filter

This function is exactly what the word means: find. Returns the element that matches the criteria and places it in an array. Let’s say we want to find all students older than 18.

Let adults = stus. Filter {(stu) -> Bool in STu. age >= 18} print(adults) //Copy the code

reduce

For reduce, our usage scenario is the combination operation of elements in the array, for example, we want to calculate the age of all students together.

let totalAges = stus.reduce(0) { (result, stu) in
        return result + stu.age
        }
    print(totalAges) // 62
Copy the code

The first argument to this function is the initial value, the first argument in the subsequent tuple is the result of each evaluation, and the second argument is the element of each iteration. Finally, the result of the calculation is returned.

Use a combination of

One of the biggest benefits of using higher-order functions is that you can do functional programming. Now let’s combine these higher-order functions through several small chestnuts.

Map String to Int and find all students with ids greater than 1002

let adults = stus.compactMap { (stu) in
        Int(stu.id)
        }.filter { (id) -> Bool in
           id > 1002
        }
    print(adults) //[1003, 1004]

Copy the code

Calculate the sum of the ages of all students older than 12

let totalAge = stus.filter { (stu) -> Bool in
            stu.age > 12
    }.reduce(0) { (result, stu) in
   return result + stu.age
   }
   print(totalAge) // 50
Copy the code