1️⃣ map
作用:对集合(数组、可选等)中的每个元素应用闭包,生成一个同样结构的新集合。
- 不会去掉
nil - 不会扁平化嵌套数组
适用场景:
- 纯转换操作,例如把数字转成字符串、平方、加前缀等
示例:
let numbers = [1, 2, 3]
let strings = numbers.map { "Number ($0)" }
print(strings) // ["Number 1", "Number 2", "Number 3"]
- 可选类型:
let number: Int? = 5
let doubled = number.map { $0 * 2 }
print(doubled) // Optional(10)
效率:
- 遍历整个集合,每个元素调用一次闭包
- 不做额外过滤或扁平化,所以最轻量,效率高
2️⃣ flatMap
flatMap 在 数组 和 可选类型 中行为不同:
数组
-
作用:映射数组元素并“扁平化”一层
-
常用于:
- 将嵌套数组变成一维数组
- 映射后返回数组,再扁平化
示例:
let nested = [[1, 2], [3, 4]]
let flattened = nested.flatMap { $0 }
print(flattened) // [1, 2, 3, 4]
let numbers = [1, 2, 3]
let repeated = numbers.flatMap { Array(repeating: $0, count: $0) }
print(repeated) // [1, 2, 2, 3, 3, 3]
可选类型
- 作用:避免可选嵌套(Optional<Optional>)
- 常用于链式可选操作
let str: String? = "123"
let number = str.flatMap { Int($0) }
print(number) // Optional(123)
效率:
- 数组 flatMap 多了一步扁平化,可能会创建新数组,比 map 略慢
- 可选 flatMap 基本等效于 map,只是避免多层 Optional
3️⃣ compactMap
作用:类似 map,但会自动去掉返回值中的 nil
- 适合可选类型或可能返回 nil 的映射
- 相比
map + filter { $0 != nil }更简洁
示例:
let strings = ["1", "two", "3", "four"]
let numbers = strings.compactMap { Int($0) }
print(numbers) // [1, 3]
- 可选类型示例:
let number: Int? = nil
let doubled = number.compactMap { $0 * 2 }
print(doubled) // []
效率:
- 遍历集合并在同一步去掉 nil
- 比
map+filter高效,因为只遍历一次
4️⃣ 使用场景总结
| 方法 | 返回类型 | 去 nil | 扁平化 | 场景 |
|---|---|---|---|---|
map | 同类型集合 | ❌ | ❌ | 普通转换,保留结构 |
flatMap (数组) | 扁平化数组 | ❌ | ✅ | 嵌套数组扁平化,映射后数组 |
flatMap (Optional) | Optional | ❌(自动解 Optional) | ✅ | 链式可选操作,避免 Optional |
compactMap | 同类型集合(去掉 nil) | ✅ | ❌ | 映射可能返回 nil 的值,自动过滤 nil |
5️⃣ 效率对比总结
- map 最轻量,直接遍历,不做额外操作
- compactMap 遍历一次,顺便过滤 nil,比
map + filter快 - flatMap(数组)需要额外扁平化操作,比 map/compactMap 稍慢
- flatMap(Optional)效率与 map 接近
💡 经验法则:
- 想保留元素结构 → 用
map - 想去掉 nil → 用
compactMap - 想扁平化嵌套数组 → 用数组
flatMap - 链式可选处理 → 用可选
flatMap