Swift uses higher-order functions

Higher-order functions commonly used in Swift include map, flatMap, filter, and reduce

1. map

A map can process each element in an array once

  1. Take a look at the map example below
Let stringArray = [" objective-C ", "Swift", "HTML", "CSS", "JavaScript"] String) -> Int { return string.characters.count } stringArray.map(stringCount) stringArray.map({string -> Int in return String. Characters. count}) // $0 represents each element in the array.Copy the code
  1. Let’s look at the definition of map in Swift and see that it can be used for Optionals and SequenceType (e.g. arrays, dictionaries, etc.). Code:
public enum Optional<Wrapped> : _Reflectable, NilLiteralConvertible { /// If `self == nil`, returns `nil`. Otherwise, returns `f(self!) `. @warn_unused_result public func map<U>(@noescape f: (Wrapped) throws -> U) rethrows -> U? } extension CollectionType { /// Returns an `Array` containing the results of mapping `transform` /// over `self`. /// /// - Complexity: O(N). @warn_unused_result public func map<T>(@noescape transform: (Self.Generator.Element) throws -> T) rethrows -> [T] }Copy the code

@warn_unused_result: indicates that the compiler will warn if the method return value is not checked or used. @noescape: Indicates that the transform closure is a non-escape closure that can only be executed within the current function map, not outside the current function. This allows the compiler to know exactly what the runtime context is (and therefore, not write self in a non-escape closure) and to do some optimizations.

  1. To map Optionals, simply unpack the optional value if it has a value, call this function, and return an optional value. Note that the returned optional value type may be different from the original optional value type:
Type: Int? , return value type: String? var value:Int? = 1 var result = value.map { String("result = \($0)") } /// "Optional("result = 1")" print(result) var value:Int? = nil var result = value.map { String("result = \($0)") } /// "nil" print(result)Copy the code
  1. Perform a map operation on SequenceType

We can use the Map method to iterate over all the elements in the array and do the same thing to each of them (function method). The map method returns the array after the operation.

We can compare the traditional for-in operation with the map operation:

1. Traditional writing: Var values = [1,3,5,7] var results = [Int]() for var value in values {value *= 2 results. Append (value)} //"[2, 6, 10, 14]" print(results) // The traditional for-in implementation has a lot of code, is not simple, and is not as efficient as higher-order functions. Map ({(element) -> Int in return element * 2}) //"[2, 6, 10, 14]"  let results = values.map { $0 * 2 } //"[2, 6, 10, 14]" 3.Copy the code

From the code comparison above, we can see how elegant high-order function simplification can be, just like writing poetry. Let’s see how we can shorten it so that we don’t even need a return statement

  • Step 1 Since the closure function body is short, we’ll rewrite it as a line:
let results = values.map ({ (element) -> Int in return element * 2 })
//"[2, 6, 10, 14]"

Copy the code
  • Step 2 Since our closure is passed as a parameter to a map, the system can infer its arguments and return values, since its arguments must be functions of type (Element) -> Int. Therefore, the return value type, ->, and the parentheses surrounding the argument can be ignored:
let results = values.map ({ element  in return element * 2 })
//"[2, 6, 10, 14]"

Copy the code
  • Third, single-line expression closures can implicitly return the result of a closure by omitting return: Since the closure body contains a single expression, Element * 2, that returns an Int, the same type as the closure used for map in our example (which is actually generic), we can omit return.
let results = values.map ({ element  in element * 2 })
//"[2, 6, 10, 14]"

Copy the code
  • Since Swift automatically provides parameter abbreviations for inline closures, you can use 0,0,0,1,$2… Get closures 1,2,3… A parameter.

    If you use a parameter abbreviation in a closure expression, you can omit its definition from the closure parameter list, and the type of the corresponding parameter abbreviation is inferred from the function type. The in keyword can also be omitted:

Let results = values.map ({$0 * 2})//$0 represents the first parameter in the closure. / / "[2, 6, 10, 14]"Copy the code
  • Since our closure is passed as the last argument to the map function, we can tag the closure expression:
let results = values.map (){ $0 * 2 }
//"[2, 6, 10, 14]"
Copy the code

If the function takes only a closure expression as an argument, you can even omit () when using trailing closures:

let results = values.map { $0 * 2 }
//"[2, 6, 10, 14]"
Copy the code

2. flatMap

  1. The array returned by flatMap does not contain nil, and it unpacks Optional
let array = ["Apple", "Orange", "Puple", ""]

let arr1 = array.map { a -> Int? in
    let length = a.characters.count
    guard length > 0 else { return nil }
    return length  
}
arr1 // [{some 5}, {some 6}, {some 5}, nil]

let arr2 = array.flatMap { a-> Int? in
    let length = a.characters.count
    guard length > 0 else { return nil}
    return length    
}    
arr2 // [5, 6, 5]
Copy the code
  1. FlatMap can also open an array containing an array (two-dimensional array, n-dimensional array) into a new array
let array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

let arr1 = array.map{ $0 }
arr1 // [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

let arr2 = array.flatMap{ $0 }
arr2 // [1, 2, 3, 4, 5, 6, 7, 8, 9]
Copy the code
  1. FlatMap can also combine two different arrays into a single array by multiplying the number of elements of the previous two arrays
let fruits = ["Apple", "Orange", "Puple"]
let counts = [2, 3, 5]

let array = counts.flatMap { count in
    fruits.map ({ fruit in
         return fruit + "  \(count)"            
    })   
}
array // ["Apple 2", "Orange 2", "Puple 2", "Apple 3", "Orange 3", "Puple 3", "Apple 5", "Orange 5", "Puple 5"]
Copy the code

3. filter

Filer: Filters the elements of an array according to a certain rule

Let stringArray = [" objective-c ", "Swift", "HTML", "CSS", "JavaScript"] func stringCountLess10(string: String) -> Bool { return string.characters.count < 10 } stringArray.filter(stringCountLess10) stringArray.filter({string -> Bool in return string.characters.count < 10}) // $0 indicates each element in the array stringarray. filter{return $0. Characters. count < 10 }Copy the code

4. reduce

Reduce: computes the elements of an array

Let stringArray = [" objective-C ", "Swift", "HTML", "CSS", "JavaScript"] appendString(string1: String, string2: String) -> String { return string1 == "" ? string2 : String1 + ", "+ string2} // the first argument in the reduce method is the initial value stringArray.reduce("", appendString) stringarray. reduce("", {(string1, string2) -> String in return string1 == "" ? String2: string1 + ", "+ string2}) // $0 indicates the result of the calculation. $1 indicates each element in the array. $1: $0 + ", "+ $1})Copy the code

Since the | address

Thanks for watching.

See this address for more swift tutorials

Swift book information download address