前言
在RxSwift中罚屋,map
, flatMap
兩個(gè)操作符用的比較算是比較頻繁的即碗,開始的時(shí)候?qū)?code>flatMap理解并不是那么深刻男应,下面就一個(gè)例子來說下自己對(duì)于flatMap
的認(rèn)識(shí):
Observable.of(1, 2, nil ,4)
.flatMap { $0 == nil ? Observable.empty() : Observable.just($0!) }
.subscribe(onNext: {
print($0)
})
開始
其實(shí)說到flatMap
,它相對(duì)于map
的不同就是所謂的降維;但是如果用降維來解釋如上的栗子配椭,好像并不那么貼切虫溜?
或許是筆者理解不夠透徹,希望讀者可以給出自己的解釋
接著
因?yàn)槔踝又械?code>observable并不是所謂的inner observables
股缸;栗子中的輸出結(jié)果是:
1
2
4
如果flatMap
換成map
衡楞,輸出結(jié)果如下:
RxSwift.Just<Swift.Int>
RxSwift.Just<Swift.Int>
RxSwift.Empty<Swift.Int>
RxSwift.Just<Swift.Int>
結(jié)果截然不同!所以下面筆者說下自己的理解:
map
和 flatMap
敦姻,兩個(gè)操作符都是將observable
中的元素進(jìn)行變換瘾境。map
操作符變換后的元素類型就是閉包返回的類型,所以本文栗子中使用map
后替劈,訂閱輸出的就是RxSwift.%%
類型寄雀;而flatMap
閉包返回的類型都是Observable
類型得滤,但是變換后的元素是Observable
類型中Element
的類型陨献,所以栗子中使用flatMap
后輸出的依然是 Int
類型。
栗子中flatMap
閉包每次返回的Observable
將其中的element
發(fā)送到一個(gè)新的Observable
懂更,這個(gè)新的Observable
會(huì)被訂閱者所訂閱眨业,這個(gè)新的Observable
就可以說明flatMap
的降維,也是所謂的flat
沮协。
然后
因?yàn)槔踝又凶畛醯?code>Observable中有一個(gè)元素為空龄捡,所以Observable
中Element
類型應(yīng)該是Optional
,但是經(jīng)過flatMap
后輸出的卻不是慷暂,說明flatMap
可以過濾Observable
中為空的element
聘殖。
之所以能過濾空的element
,主要還是因?yàn)?code>flatMap會(huì)新建一個(gè)Observable
行瑞,因?yàn)槔踝又虚]包奸腺,當(dāng)元素為空的時(shí)候返回的是一個(gè)空的Observable
,所以新的Observable
并不會(huì)接收到其中的element
血久,之后訂閱者所輸出的也就不存在空的元素突照,所以類型自然也就不是Optional
。
Swift中的
flatMap
氧吐,同樣的也可以過濾空的元素
["ab", "cc", nil, "dd"].flatMap { $0 }
["ab", "cc", nil, "dd"].filter { $0 != nil} .map { $0! }
此時(shí)數(shù)組是["ab", "cc", "dd"]
,而且不是Optional
類型讹蘑,只是使用flatMap
更佳簡(jiǎn)潔高效;因?yàn)閮?nèi)部使用了if let
,所以達(dá)到了過濾空元素的效果筑舅。
Functor and Monad 更新于2017-12-04
Functor and Monad是函數(shù)式編程的重要概念座慰,筆者之前也不是太理解,只是聽過名稱而已翠拣,其實(shí)他們的定義和map角骤,flatMap關(guān)系很大:
flatMap其實(shí)是一種特殊的map,所謂的降維是因?yàn)閒lat的原因
下面是筆者對(duì)于數(shù)組類型實(shí)現(xiàn)的map, flatten, flattenMap:
extension Array {
func myMap<T>(_ transform: (Element) -> T) -> [T] {
var result: [T] = []
result.reserveCapacity(count)
for x in self {
result.append(transform(x))
}
return result
}
func myFlatten<T>(elements: [[T?]]) -> [T] {
var result: [T] = []
for arr in elements {
for item in arr {
if let num = item {
result.append(num)
}
}
}
return result
}
func myFlattenMap<T>(_ transform: (Element) -> [T?]) -> [T] {
return myFlatten(elements: myMap(transform))
}
}
根據(jù)上面的代碼,其實(shí)functor和monad的定義也就很容易理解了:
Functor:
map
函數(shù)接受一個(gè)閉包作為參數(shù)邦尊,作用與容器類型(數(shù)組背桐,optional,result)蝉揍,通過傳入的閉包改變?nèi)萜黝愋蛢?nèi)部的值链峭,從而得到一個(gè)全新的容器
; 所謂functor就是實(shí)現(xiàn)了map功能的類型;
Monad: monad 是functor中的一種又沾,相比functor不僅實(shí)現(xiàn)了map功能弊仪,而且實(shí)現(xiàn)了flattenMap的功能护赊;