iOS_Swift高阶函数
1. 基础知识
1.1 定义
高阶函数:higher-order function
如果一个函数:
- 接受一个或多个函数当作参数
- 把一个函数当作返回值
那么这个函数就被称做高阶函数。
例如:
let numbers = [1, 4, 2, 3]
let res = numbers.sort {
$0 < $1
}
看着不像是函数作为参数,是因为 Swift
尾随闭包 Trailing Closure
的特性。Swift
允许当函数的最后一个参数是闭包时,可以以紧跟 { }
的形式,将最后一个闭包的内容附加在函数后面。
所以,以下两行代码是等价的:
// 正常写法,函数是作为 sort 的参数
arr.sort({ $0 < $1 })
// Trailing Closure 写法,更简洁明了
arr.sort { $0 < $1 }
1.2 闭包语法
// 完整语法
nums.map({ (value: Int) -> Int in return value * 2 })
// 闭包语法
nums.map{ (value: Int) -> Int in return value * 2 }
// 省略返回值类型
nums.map{ (value: Int) in return value * 2 }
// 省略参数类型
nums.map{ value in return value * 2 }
// 省略 return
nums.map{ value in value * 2 }
// 省略参数
nums.map{ $0 * 2 }
2. 高阶函数
2.1 map
2.1.1 集合类使用
遍历集合处理后,组成新的集合
// 将数组中的字符串转换为小写字母
let cast = ["Vivien", "Marlon", "Kim", "Karl"]
let lowercaseNames = cast.map { $0.lowercased() }
print(lowercaseNames) // ["vivien", "marlon", "kim", "karl"]
// 获得数组中字符串的长度
let letterCounts = cast.map { $0.count }
print(letterCounts) // [6, 6, 3, 4]
2.1.2 Optional使用
Optional
也可以使用 map
:
let num: Int? = 2
var res = num.map { $0 * 2 }
print(res)
/// 而不需要像以下这样解包
if let num = num {
res = num * 2
} else {
res = nil
}
2.1.3 map 时获得 index
需要在 map
前使用 enumerated
:
let indexRes = cast.enumerated().map{ (index, element) in
return "\(index):\(element)"
}
print(indexRes)
2.2 compactMap
Array
和 Set
使用 compactMap
可获得非空集合:
let possibleNumbers = ["1", "2", "three", "///4///", "5"]
let mapped = possibleNumbers.map { Int($0) }
print(mapped) // [Optional(1), Optional(2), nil, nil, Optional(5)]
// compactMap 获得非 optional 元素
let compactMapped = possibleNumbers.compactMap { Int($0) }
print(compactMapped) // [1, 2, 5]
Dictionary
得用 compactMapValues
如下。
2.3 compactMapValues
Dictionary
使用 compactMapValues
可获得非空的键值对集合:
let dict = ["a": "1", "b": "three", "c": "///4///"]
let maped = dict.mapValues { Int($0) }
print(maped) // ["a": Optional(1), "b": nil, "c": nil]
let compactMaped = dict.compactMapValues { Int($0) }
print(compactMaped) // ["a": 1]
2.4 flatMap
flatMap
可将多维的集合,降低为一维:
let dict = ["Momo": [1, 2, 3], "Bibi": [4, 5, 6]]
let res1 = dict.map { $0.value }
print(res1) // [[4, 5, 6], [1, 2, 3]]
let res2 = dict.flatMap { $0.value }
print(res2) // [4, 5, 6, 1, 2, 3]
2.5 filter
filter
可过滤出符合条件的元素集合
// 过滤字符串长度小于5的
let cast = ["Vivien", "Marlon", "Kim", "Karl"]
let shortNames = cast.filter { $0.count < 5 }
print(shortNames) // ["Kim", "Karl"]
2.6 reduce
reduce
可对集合遍历累积处理结果:
// 计算所有元素和
let numbers = [1, 2, 3, 4]
let res = numbers.reduce(0, { x, y in
// 第一个参数为上次处理结果
// 第二个参数为当前遍历到的元素
x + y
})
print(res) // 10
3.练习
3.1 用 reduce 实现 map
let arr = [1, 3, 2]
let res = arr.reduce([]) { (a: [Int], element: Int) -> [Int] in
var tmp = Array(a)
tmp.append(element * 2)
return tmp
}
// res = [2, 6, 4]
关键点:result
用数组
3.2 用 reduce 一次求出数组中奇数的和、以及偶数乘积
let arr = [1, 3, 2, 4]
let res: (Int, Int) = arr.reduce((0, 1)) { (a :(Int, Int), element: Int) -> (Int, Int) in
if element % 2 == 0 {
return (a.0, a.1 * element)
} else {
return (a.0 + element, a.1)
}
}
// res = (4, 8)
关键点:result
用元组表示
3.3 使用高阶函数求一个数组中偶数的平方和
let arr = [1, 3, 2, 4]
let res = arr.filter {
$0 % 2 == 0
}.map {
$0 * $0
}.reduce(0) {
$0 + $1
}
Reference:
Apple Documentation for swift
Swift 烧脑体操(三) - 高阶函数
深入浅出Swift高阶函数-Map、Filter、Reduce
swift小知识点之高阶函数之map, filter, reduce