抽空看了一下这几个操作符,我们先来看一下权威的 Apple 文档怎么写的:
1. map
/// Returns an array containing the results of mapping the given closure
/// over the sequence's elements.
///
/// In this example, `map` is used first to convert the names in the array
/// to lowercase strings and then to count their characters.
///
/// 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]
///
/// - Parameter transform: A mapping closure. `transform` accepts an
/// element of this sequence as its parameter and returns a transformed
/// value of the same or of a different type.
/// - Returns: An array containing the transformed elements of this
/// sequence.
@inlinable public func map<T>(_ transform: (Element) throws -> T) rethrows -> [T]
先看例子,cast
为一个字符串数组,通过map
操作后,$0.lowercased()
为转为小写字母,lowercaseNames
为cast
的全部小写数组。
我们再看最后一行,首先map
操作规定的类型是个范型<T>
,block 里返回T
类型的元素,是确定值,非可选值,map
操作后结果为[T]
。可以理解为map
操作把原数据转为新的类型。
2. flatMap
/// Returns an array containing the concatenated results of calling the
/// given transformation with each element of this sequence.
///
/// Use this method to receive a single-level collection when your
/// transformation produces a sequence or collection for each element.
///
/// In this example, note the difference in the result of using `map` and
/// `flatMap` with a transformation that returns an array.
///
/// 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]
///
/// In fact, `s.flatMap(transform)` is equivalent to
/// `Array(s.map(transform).joined())`.
///
/// - Parameter transform: A closure that accepts an element of this
/// sequence as its argument and returns a sequence or collection.
/// - Returns: The resulting flattened array.
///
/// - Complexity: O(*m* + *n*), where *n* is the length of this sequence
/// and *m* is the length of the result.
@inlinable public func flatMap<SegmentOfResult>(_ transform: (Element) throws -> SegmentOfResult) rethrows -> [SegmentOfResult.Element] where SegmentOfResult : Sequence
例子中,可以看到flatMap
操作,把数据都 压扁 了,也就是 降维。我们看一下最后一行,先需要满足的是SegmentOfResult : Sequence
,就是说SegmentOfResult
满足Sequence
协议。同样,block 里返回SegmentOfResult
元素,是确定值,非可选值,输出结果是由SegmentOfResult
的子元素SegmentOfResult.Element
构成的数组。
文档中还有这几行代码:
@available(swift, deprecated: 4.1, renamed: "compactMap(_:)", message: "Please use compactMap(_:) for the case where closure returns an optional value")
public func flatMap<ElementOfResult>(_ transform: (Element) throws -> ElementOfResult?) rethrows -> [ElementOfResult]
这个方法,在 block 中返回了一个可选值的ElementOfResult
,也就是说返回值可以为nil
。但是这个方法被废弃了,提示我们使用compactMap(_:)
。
3. compactMap
/// Returns an array containing the non-`nil` results of calling the given
/// transformation with each element of this sequence.
///
/// Use this method to receive an array of non-optional values when your
/// transformation produces an optional value.
///
/// In this example, note the difference in the result of using `map` and
/// `compactMap` with a transformation that returns an optional `Int` value.
///
/// 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]
///
/// - Parameter transform: A closure that accepts an element of this
/// sequence as its argument and returns an optional value.
/// - Returns: An array of the non-`nil` results of calling `transform`
/// with each element of the sequence.
///
/// - Complexity: O(*m* + *n*), where *n* is the length of this sequence
/// and *m* is the length of the result.
@inlinable public func compactMap<ElementOfResult>(_ transform: (Element) throws -> ElementOfResult?) rethrows -> [ElementOfResult]
例子中显示了,我们的mapped
中含有nil
,通过compact
操作后,nil
值被过滤掉了。所以可以理解该方法为去掉空元素。
再来看一下 RxSwift 中的对应操作符:
1. map
/**
Projects each element of an observable sequence into a new form.
- seealso: [map operator on reactivex.io](http://reactivex.io/documentation/operators/map.html)
- parameter transform: A transform function to apply to each source element.
- returns: An observable sequence whose elements are the result of invoking the transform function on each element of source.
*/
public func map<Result>(_ transform: @escaping (Element) throws -> Result)
-> Observable<Result> {
return Map(source: self.asObservable(), transform: transform)
}
2. flatMap
/**
Projects each element of an observable sequence to an observable sequence and merges the resulting observable sequences into one observable sequence.
- seealso: [flatMap operator on reactivex.io](http://reactivex.io/documentation/operators/flatmap.html)
- parameter selector: A transform function to apply to each element.
- returns: An observable sequence whose elements are the result of invoking the one-to-many transform function on each element of the input sequence.
*/
public func flatMap<Source: ObservableConvertibleType>(_ selector: @escaping (Element) throws -> Source)
-> Observable<Source.Element> {
return FlatMap(source: self.asObservable(), selector: selector)
}
3. compactMap
/**
Projects each element of an observable sequence into an optional form and filters all optional results.
Equivalent to:
func compactMap<Result>(_ transform: @escaping (Self.E) throws -> Result?) -> RxSwift.Observable<Result> {
return self.map { try? transform($0) }.filter { $0 != nil }.map { $0! }
}
- parameter transform: A transform function to apply to each source element and which returns an element or nil.
- returns: An observable sequence whose elements are the result of filtering the transform function for each element of the source.
*/
public func compactMap<Result>(_ transform: @escaping (Element) throws -> Result?)
-> Observable<Result> {
return CompactMap(source: self.asObservable(), transform: transform)
}
比较一下,原生操作符 block 中返回ElementOfResult
,而输出[ElementOfResult]
;不同的是,RxSwift 这几个操作符 block 中返回Result
的值,但会输出一个Observable<Result>
。