加深理解代替单纯记忆
map相关方法有哪些
mapflatMapcompactMap
哪些地方中有这些方法
- Sequence protocol
- Optional(没有compactMap方法)
Sequence
- 常见的数据结构有,Array、Dictionary、Set等都遵循该协议
方法声明
-
func map<T>(_ transform: (Self.Element) throws -> T) rethrows -> [T] -
func flatMap<SegmentOfResult>(_ transform: (Self.Element) throws -> SegmentOfResult) rethrows -> [SegmentOfResult.Element] where SegmentOfResult : Sequence -
func compactMap<ElementOfResult>(_ transform: (Self.Element) throws -> ElementOfResult?) rethrows -> [ElementOfResult] -
func flatMap<ElementOfResult>(_ transform: (Self.Element) throws -> ElementOfResult?) rethrows -> [ElementOfResult]- 从Swift 4.1开始,该方法由于不好用,已被废弃
map方法
- 之所以叫做map,核心的工作就是做
映射 - 将sequence中的
每个元素,通过closure的处理一对一的映射到一个新序列中 - 因为是泛型方法,需要指定映射后数组元素的类型
- 也就是说,map后的sequence和原sequence的元素数是相等的
let cast = ["Vivien", "Marlon", "Kim", "Karl"]
let lowercaseNames = cast.map { $0.lowercased() }
// 'lowercaseNames' == ["vivien", "marlon", "kim", "karl"]
let letterCounts = cast.map { $0.count }
// 'letterCounts' == [6, 6, 3, 4]
flatMap方法
- 核心工作仍然是通过closure进行映射
- 通过声明可知,closure的返回值也要是一个Sequence
- 这适用于对原序列的每个元素,每次映射要映射出一个新序列的情况
- 仔细观察方法的返回结果
[SegmentOfResult.Element],并不是我们想当然的[SegmentOfResult],这就是flat的作用 - flat是该方法的特点--平铺,即将返回的序列进行
展开操作
let numbers = [1, 2, 3, 4]
let mapped = numbers.map { Array(repeating: $0, count: $0) }
// [[1], [2, 2], [3, 3, 3], [4, 4, 4, 4]]
let flatMapped = numbers.flatMap { Array(repeating: $0, count: $0) }
// [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
compactMap方法
- 核心工作也是通过closure进行映射
- 与map的不同就在于
compact一词(简洁的意思),返回结果的数组中被精简了- 所有optional的值会自动解包
- 所有nil的值会被干掉
- 所以结果可能和原序列元素数不同
let possibleNumbers = ["1", "2", "three", "///4///", "5"]
let mapped: [Int?] = possibleNumbers.map { str in Int(str) }
// [1, 2, nil, nil, 5]
let compactMapped: [Int] = possibleNumbers.compactMap { str in Int(str) }
// [1, 2, 5]
不再使用的flatMap方法
- 废弃的flatMap方法在closure完成时进行一次wrap,最后又会进行一次解包,浪费资源
- 因为有另一个同名的方法,在使用上容易产生歧义
- 引入
compactMap来代替该方法
Optional
注意
Optional中仅有map和flatMap方法,没有compactMap
方法声明
需要说明一点,下面方法transform参数中的Wrapped类型,是Optional的泛型类型,也就是说传给transform的参数是经过解包的、实际上表示的内容,比如Int?,那此处Wrapped表示的就是Int
func map<U>(_ transform: (Wrapped) throws -> U) rethrows -> U?func flatMap<U>(_ transform: (Wrapped) throws -> U?) rethrows -> U?
总结
- 两个map方法都是将optional解包后传递给transform,transform结束后,结果作为方法的返回值
- 两个方法都返回optional的值
- 当optional是nil的时候,两个方法都会返回nil
- 不同点在于
flatMap的transform允许返回optional值