Swift Map與CompactMap區別
Map與CompactMap區別
對於不同點,我們先說說相同點:
Map和FlatMap都可以用在Optionals和SequenceTypes上(如:數組、字典等)。
對於不同點:
先說說Swift4新加入的新特性compactMap;
flatMap會將transform函數的返回類型先拍扁,在組合成本身的複合類型,Swift標準庫有3個 flatMap
Sequence.flatMap<S>(_: (Element) -> S)
-> [S.Element] where S : Sequence
Optional.flatMap<U>(_: (Wrapped) -> U?) -> U?
Sequence.flatMap<U>(_: (Element) -> U?) -> [U]
在 Swift 4.1中引入的compactMap新函數實際上是對第三個方法的重命名。
map 最終將它們組成一個二維的數組;
flatMap相關
Sequence.flatMap區別
flatMap 中執行的 closure 返回的是同樣的數組,但是 flatMap 將每一個返回的數組都拍扁,取出它的元素,構成一個大的一維數組。
let numbers = [[1, 2, 3, 4], [5, 6], [7]]
let maped = numbers.map { $0 }
let flatMapped = numbers.flatMap { $0 }
print(maped)
print(flatMapped)
/// [[1, 2, 3, 4], [5, 6], [7]]
/// [1, 2, 3, 4, 5, 6, 7]
Optional.flatMap區別
Optional的版本知道的和日常使用的就沒有那麼多了。先仔細看一下這兩個函數的定義,區別僅在一個處:
func map<U>( transform: (Wrapped) -> U) -> U?
func flatMap<U>( transform: (Wrapped) -> U?) -> U?
map是閉包內return爲非可選項,但最終返回值爲可選項,即閉包return後又套了一層可選項。
flatMap是閉包內return爲可選項,最終返回值也爲可選項,即閉包內return後對可選項進行解包,最終又套了一層可選項。
那麼什麼時候使用 Optional Chaining,什麼時候使用 Optional 的 Mapping 呢?
我認爲,他們的差異在於 receiver 在類型轉換過程中承擔的角色,Optional Chaining 中只能作爲 receiver,而 Optional Mapping 函數還能作爲參數,更爲通用,因而第一個例子只能用 Mapping 實現;另一個方面,Optional Chaining 只能寫成串聯表達式,而 closure 當中可以寫更復雜的轉換邏輯。
還是用例子來說明:
let possibleNumber: Int? = Int("42")
let nonOverflowingSquare = possibleNumber.flatMap {
x -> Int? in
let (result, overflowed) = x.multipliedReportingOverflow(by: x)
return overflowed ? nil : result
}
Optional.compactMap區別
衆所周知,flatMap可以作爲降維使用,除了 flat 之外其實還有 filter 的作用,在使用時容易產生歧義,所以社區認爲最好把第二個版本重新拆分出來,使用一個新的方法命名,就產生了這個提案 SE-0187。
最初這個提案用了filterMap這個名字,但後來經過討論,就決定參考了 Ruby 的Array::compact方法,使用compactMap這個名字。
如下是改版前後的代碼區別,可以看到用法相同,僅針對名字進行了更改。
Sequence.flatMap<U>(_ : (Element) -> U?) -> [U]
Sequence.compactMap<U>(_ : (Element) -> U?) -> [U]
compactMap,可以把一個集合中的空值去除,並且返回一個去除nil值得數組
下面通過代碼例子說明下區別:
let numbers = ["1", "2", "three", "///5///", "5"]
let mapResult = numbers.map { (number) -> Int? in
return Int(number)
}
print(mapResult)
// [Optional(1), Optional(2), nil, nil, Optional(5)]
let compactMapResult = numbers.compactMap { (number) -> Int? in
return Int(number)
}
print(compactMapResult)
// [1, 2, 5]
相關文章:
Swift Map詳解.
Swift flatMap詳解.