记录一下Swift中的map和flatMap。git
网上不少文章都是以前的,那时flatMap的定义还有两个重载的函数,对应的源码也是以前版本的~所以我在没看源码前,对flatMap的实现有了一些误解。由下面这段代码的输出引起的本次探索。github
let arr = [1, 2, 3]
print(arr.map{"NO.\($0)"})
print(arr.flatMap{"NO.\($0)"})
复制代码
先贴源码swift
@inlinable
public func map<T>(
_ transform: (Element) throws -> T
) rethrows -> [T] {
let initialCapacity = underestimatedCount
var result = ContiguousArray<T>()
result.reserveCapacity(initialCapacity)
var iterator = self.makeIterator()
// Add elements up to the initial capacity without checking for regrowth.
for _ in 0..<initialCapacity {
result.append(try transform(iterator.next()!))
}
// Add remaining elements, if any.
while let element = iterator.next() {
result.append(try transform(element))
}
return Array(result)
}
复制代码
这段源码和网上大多文章同样,map里面的处理以下。api
结合咱们从Xcode中看到的解释以及源码,咱们能够知道flatMap就是返回的Array(s.map(transform).joined())数组
public func flatMap<SegmentOfResult>(
_ transform: @escaping (Elements.Element) -> SegmentOfResult
) -> LazySequence<
FlattenSequence<LazyMapSequence<Elements, SegmentOfResult>>> {
return self.map(transform).joined()
}
复制代码
因此,以前的实现方法appendContents那种都无效了。所以开头那个demo输出也和以前不同了(按以前的实现,flatMap输出的和map同样),结果以下。bash
["NO.1", "NO.2", "NO.3"]
["N", "O", ".", "1", "N", "O", ".", "2", "N", "O", ".", "3"]
复制代码
用flatMap的时候,结果返回有可选值的时候,好比对数组里面的字符串转成Int,Xcode会提示咱们用compactMap方法。 闭包
我是看的唐巧大神的文章Swift 烧脑体操(四) - map 和 flatMapapp
本身也整理了一下。 源码地址函数
@inlinable
public func map<U>(
_ transform: (Wrapped) throws -> U
) rethrows -> U? {
switch self {
case .some(let y):
return .some(try transform(y))
case .none:
return .none
}
}
@inlinable
public func flatMap<U>(
_ transform: (Wrapped) throws -> U?
) rethrows -> U? {
switch self {
case .some(let y):
return try transform(y)
case .none:
return .none
}
}
复制代码
这段代码,乍一看相同,不一样之处在于:ui
因此map有可能形成多重Optional的问题,Optional嵌套可看唐巧大神的文章 https://blog.devtang.com/2016/02/27/swift-gym-1-nested-optional/。