ご存知のとおり、Swift2からのArray.flatmap()は、Optionalを返す関数を渡すとArrayに戻してくれて、かつnilを捨ててくれるという便利機能が実装されています。
参考: Swift 2.0の新しいflatMapが便利過ぎる
http://qiita.com/koher/items/6a95cb8edb04fb81f787
RxSwiftのObservableにも同じ使い勝手で使えるflatmapを実装することができます。
便利そうな気もしますが、わかりにくいかもしれません。
extension Observable {
/**
example:
Observable<String>.of("1", "a", "3", "4")
.flatMap { Int($0) }
.subscribeNext { print("\($0)") }
result:
1
3
4
*/
func flatMap<T>(selector: (E) throws -> T?) -> Observable<T> {
return flatMap { try selector($0).map { Observable<T>.just($0) } ?? Observable<T>.empty() }
}
}
extension Driver {
/**
example:
Driver<String>.of("1", "a", "3", "4")
.flatMap { Int($0) }
.driveNext { print("\($0)") }
result:
1
3
4
*/
func flatMap<T>(selector: (E) -> T?) -> Driver<T> {
return flatMap { selector($0).map { Driver<T>.just($0) } ?? Driver<T>.empty() }
}
}
例
たとえばこんな処理が、、、
Observable<String>.of("1", "a", "3", "4", "5", "c", "d", "8")
.map { (v : String) -> Int? in return Int(v) } // <- Int(String)が 失敗したときnilを返す
.filter { (v : Int?) -> Bool in return (v != nil) } // <- 失敗した結果を捨てる
.map { (v : Int?) -> Int in return v! } // <- Optionalをunwrap
.subscribeNext { print("\($0)") }
または、RxSwiftExt ( https://github.com/RxSwiftCommunity/RxSwiftExt ) をお使いの場合はこんな感じになると思いますが、、
Observable<String>.of("1", "a", "3", "4", "5", "c", "d", "8")
.map { (v : String) -> Int? in return Int(v) }
.unwrap ()
.subscribeNext { print("\($0)") }
こんな感じで書けるようになります
Observable<String>.of("1", "a", "3", "4", "5", "c", "d", "8")
.flatMap { (v : String) -> Int? in return Int(v) }
.subscribeNext { print("\($0)") }
しかしやはり、便利そうな気もしますが、わかりにくいかもしれません。
gistはこちら
https://gist.github.com/gamako/01a3646103f065473ade766f9ad21287