Swift高阶函数
Swift高阶函数
高阶函数是指可以接收函数作为参数或者返回函数作为结果的函数。Swift 标准库提供了多个强大的高阶函数,主要用于集合类型的操作。以下是 Swift 中常用的高阶函数及其使用场景:
1. map(_:)
功能:对集合中的每个元素进行转换,返回一个新的数组。
使用场景:当你需要对数组中的每个元素进行相同操作并得到新数组时。
let numbers = [1, 2, 3, 4]
let squared = numbers.map { $0 * $0 } // [1, 4, 9, 16]2. compactMap(_:)
功能:类似于 map,但会自动过滤掉 nil 值。
使用场景:转换可能产生 nil 的情况,并希望自动去除 nil 值。
let strings = ["1", "2", "three", "4"]
let numbers = strings.compactMap { Int($0) } // [1, 2, 4]3. flatMap(_:)
功能:将二维数组"压平"为一维数组,或处理嵌套可选值。
使用场景:
- 处理嵌套数组
- 处理嵌套可选值(Swift 4.1+ 中对于可选值推荐使用 compactMap)
let nestedArray = [[1, 2, 3], [4, 5, 6]]
let flattened = nestedArray.flatMap { $0 } // [1, 2, 3, 4, 5, 6]4. filter(_:)
功能:根据条件过滤集合中的元素。
使用场景:需要从集合中筛选符合条件的元素时。
let numbers = [1, 2, 3, 4, 5, 6]
let evens = numbers.filter { $0 % 2 == 0 } // [2, 4, 6]5. reduce(_:_:)
功能:将集合中的所有元素组合成一个值。
使用场景:需要计算总和、拼接字符串或任何需要将集合"缩减"为单个值的操作。
let numbers = [1, 2, 3, 4]
let sum = numbers.reduce(0) { $0 + $1 } // 10
let product = numbers.reduce(1, *) // 246. sorted(by:)
功能:根据条件对集合进行排序。
使用场景:需要自定义排序规则时。
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
let sortedNames = names.sorted(by: { $0 < $1 }) // 升序排列7. forEach(_:)
功能:对集合中的每个元素执行操作。
使用场景:需要对每个元素执行操作但不需要返回值时(与 map 的区别)。
["a", "b", "c"].forEach { print($0) }8. contains(where:)
功能:检查集合中是否包含满足条件的元素。
使用场景:需要检查集合中是否存在符合条件的元素时。
let numbers = [1, 2, 3, 4, 5]
let hasEven = numbers.contains(where: { $0 % 2 == 0 }) // true9. first(where:)/last(where:)
功能:返回集合中第一个/最后一个满足条件的元素。
使用场景:需要查找集合中第一个或最后一个符合条件的元素时。
let numbers = [10, 20, 30, 40]
let firstMultipleOf15 = numbers.first(where: { $0 % 15 == 0 }) // 3010. prefix(while:)/drop(while:)
功能:
prefix(while:):从开头开始获取满足条件的元素,直到条件不满足drop(while:):跳过开头满足条件的元素,返回剩余部分
使用场景:需要基于条件获取或跳过集合开头部分时。
let scores = [85, 90, 78, 92, 88, 76]
let goodScores = scores.prefix(while: { $0 >= 85 }) // [85, 90]
let afterFirstBad = scores.drop(while: { $0 >= 85 }) // [78, 92, 88, 76]11. zip(_:_:)
功能:将两个序列组合成一个元组序列。
使用场景:需要同时遍历两个集合时。
let names = ["Alice", "Bob", "Charlie"]
let scores = [85, 92, 78]
for (name, score) in zip(names, scores) {
print("\(name): \(score)")
}使用建议
链式调用:可以组合多个高阶函数
let result = (1...10) .filter { $0 % 2 == 0 } .map { $0 * $0 } .reduce(0, +)- 性能考虑:每个高阶函数都会创建一个新集合,对于大数据集可能需要考虑性能
- 可读性:当逻辑复杂时,有时传统的 for 循环可能更易读
这些高阶函数使 Swift 代码更加简洁、表达力更强,是函数式编程风格的重要组成部分。
补充:flatMap 与 compactMap 的区别
compactMap 不会自动将二维数组降为一维数组,这是它与 flatMap 的一个重要区别。
主要区别
compactMap:- 主要用途:在映射过程中过滤掉
nil值 - 不会自动"压平"二维数组
- 返回的数组维度与输入相同
- 主要用途:在映射过程中过滤掉
flatMap(在 Swift 4.1 及以后版本):- 主要用途:将二维数组降为一维数组
- 不处理
nil值过滤(对于可选值过滤,改用compactMap)
示例对比
1. compactMap 行为
let nestedArray = [[1, nil, 3], [nil, 5, 6]]
let result = nestedArray.compactMap { $0 }
print(result)
// 输出: [[Optional(1), nil, Optional(3)], [nil, Optional(5), Optional(6)]]
// 仍然是二维数组,只是对最外层数组进行了 nil 过滤(这里没有 nil 所以没变化)2. 正确使用 compactMap 过滤 nil
let arrayWithOptionals: [Int?] = [1, nil, 3, nil, 5]
let nonNilValues = arrayWithOptionals.compactMap { $0 }
print(nonNilValues) // 输出: [1, 3, 5]3. flatMap 降维示例
let nestedArray = [[1, 2, 3], [4, 5, 6]]
let flattened = nestedArray.flatMap { $0 }
print(flattened) // 输出: [1, 2, 3, 4, 5, 6]历史变化
Swift 4.1 之前:
flatMap有三种功能:- 二维数组降维
- 过滤 nil (类似现在的
compactMap) - 组合操作
Swift 4.1 及以后:
flatMap只保留降维功能- 过滤 nil 的功能迁移到
compactMap
如何实现带 nil 过滤的降维
如果需要同时处理二维数组降维和过滤 nil,可以组合使用:
let nestedWithOptionals = [[1, nil, 3], [nil, 5, 6]]
let result = nestedWithOptionals.flatMap { $0 }.compactMap { $0 }
print(result) // 输出: [1, 3, 5, 6]
新车即将上线 真正的项目,期待你的参与coinsrore.com
2025年10月新盘 做第一批吃螃蟹的人coinsrore.com
新车新盘 嘎嘎稳 嘎嘎靠谱coinsrore.com
新车首发,新的一年,只带想赚米的人coinsrore.com
新盘 上车集合 留下 我要发发 立马进裙coinsrore.com
做了几十年的项目 我总结了最好的一个盘(纯干货)coinsrore.com
新车上路,只带前10个人coinsrore.com
新盘首开 新盘首开 征召客户!!!coinsrore.com
新项目准备上线,寻找志同道合 的合作伙伴coinsrore.com
新车即将上线 真正的项目,期待你的参与coinsrore.com
新盘新项目,不再等待,现在就是最佳上车机会!coinsrore.com
新盘新盘 这个月刚上新盘 新车第一个吃螃蟹!coinsrore.com
2025年10月新盘 做第一批吃螃蟹的人coinsrore.com
新车新盘 嘎嘎稳 嘎嘎靠谱coinsrore.com
新车首发,新的一年,只带想赚米的人coinsrore.com
新盘 上车集合 留下 我要发发 立马进裙coinsrore.com
做了几十年的项目 我总结了最好的一个盘(纯干货)coinsrore.com
新车上路,只带前10个人coinsrore.com
新盘首开 新盘首开 征召客户!!!coinsrore.com
新项目准备上线,寻找志同道合 的合作伙伴coinsrore.com
新车即将上线 真正的项目,期待你的参与coinsrore.com
新盘新项目,不再等待,现在就是最佳上车机会!coinsrore.com
新盘新盘 这个月刚上新盘 新车第一个吃螃蟹!coinsrore.com
华纳公司合作开户所需材料?电话号码15587291507 微信STS5099
华纳公司合作开户所需材料?电话号码15587291507 微信STS5099
华纳公司合作开户所需材料?电话号码15587291507 微信STS5099
华纳公司合作开户所需材料?电话号码15587291507 微信STS5099
华纳公司合作开户所需材料?电话号码15587291507 微信STS5099
华纳公司合作开户所需材料?电话号码15587291507 微信STS5099
华纳公司合作开户所需材料?电话号码15587291507 微信STS5099
华纳公司合作开户所需材料?电话号码15587291507 微信STS5099
华纳公司开户需要哪些材料?(▲18288362750?《?微信STS5099? 】【╃q 2704132802╃】
华纳东方明珠客服电话是多少?(▲18288362750?《?微信STS5099? 】
如何联系华纳东方明珠客服?(▲18288362750?《?微信STS5099? 】
华纳东方明珠官方客服联系方式?(▲18288362750?《?微信STS5099?
华纳东方明珠客服热线?(▲18288362750?《?微信STS5099?
华纳东方明珠24小时客服电话?(▲18288362750?《?微信STS5099? 】
华纳东方明珠官方客服在线咨询?(▲18288362750?《?微信STS5099?
果博东方客服开户联系方式【182-8836-2750—】?薇- cxs20250806】
果博东方公司客服电话联系方式【182-8836-2750—】?薇- cxs20250806】
果博东方开户流程【182-8836-2750—】?薇- cxs20250806】
果博东方客服怎么联系【182-8836-2750—】?薇- cxs20250806】
华纳圣淘沙公司开户新手教程
零基础学会(183-8890-9465薇-STS5099)
华纳圣淘沙公司开户
华纳圣淘沙公司开户保姆级教程(183-8890-9465薇-STS5099)
一步步教你开通华纳圣淘沙公司账户(183-8890-9465薇-STS5099)
华纳圣淘沙公司开户分步图解
首次开户必看:(183-8890-9465薇-STS5099)
华纳圣淘沙全攻略
华纳圣淘沙公司开户实操手册(183-8890-9465薇-STS5099)
华纳圣淘沙开户流程视频教程
手把手教学:(183-8890-9465薇-STS5099)
华纳圣淘沙公司开户
华纳圣淘沙公司开户完全指南(183-8890-9465薇-STS5099)
华纳圣淘沙公司开户新手教程
零基础学会(183-8890-9465薇-STS5099)
华纳圣淘沙公司开户
华纳圣淘沙公司开户保姆级教程(183-8890-9465薇-STS5099)
一步步教你开通华纳圣淘沙公司账户(183-8890-9465薇-STS5099)
华纳圣淘沙公司开户分步图解
首次开户必看:(183-8890-9465薇-STS5099)
华纳圣淘沙全攻略
华纳圣淘沙公司开户实操手册(183-8890-9465薇-STS5099)
华纳圣淘沙开户流程视频教程
手把手教学:(183-8890-9465薇-STS5099)
华纳圣淘沙公司开户
华纳圣淘沙公司开户完全指南(183-8890-9465薇-STS5099)