和 Swift 下的 map 与 flatMap 是一样的。
Swift 中过滤 nil 的最佳方案 flatMap
是的,过滤到满足某些条件的值,但却不是过滤 nil
的最佳方案。
先来回顾一下 filter
的基本用法:
[1, 2, 3, 4, 5].filter { $0 > 2 }
// 结果是 [3, 4, 5]
那用 filter
过滤 nil
的写法就是这个样子:
let values: [Int?] = [1, 2, 3, nil, 4]
values.filter { $0 != nil }.map { $0! }
// 结果是 [1, 2, 3, 4]
但是在过滤 nil
的这个场景,显然是用 flatMap
更好些,优雅更简洁:
let values: [Int?] = [1, 2, 3, nil, 4]
value.flatMap { $0 }
// 结果是 [1, 2, 3, 4]
如果您是第一次看到这个用法,那您一定会觉得很神奇。flatMap
不是做变换的吗,为何就可以过滤 nil
。和我一起看 RxSwift 中过滤 nil
的方案,同时也会帮助您理解 Swift 中的 flatMap
是如何过滤 nil
的。
RxSwift 中过滤 nil
的方案
和 Swift 中一样,我们仍然可以用 filter
完成。
let sequence = [1, 2, 3, nil ,4].toObservable()
sequence.filter { $0 != nil }.map { $0! }
// 此时序列中的值变为 1, 2, 3, 4
来看我们如何用 flatMap
完成过滤 nil
的事情:
let sequence = [1, 2, 3, nil, 4].toObservable()
sequence.flatMap { value -> Observable<Int> in
If let value = value {
return Observable.just(value)
} else {
return Observable.empty()
}
}
通过 if let
解包,如果有值,就返回该值,没有,返回一个 empty
。
同样在 Swift 中,也是类似的,我们写成上面 Rx 的样子:
let values: [Int?] = [1, 2, 3, nil, 4]
value.flatMap { value -> Int? In
if let value = value {
return value
} else {
return nil
}
}
返回 nil
表示抛弃该值但其实上面的写法是和 flatMap { $0 }
完全一样的效果,这里请读者自行思考。
更多关于 RxSwift 的 map
flatMap
,在学习 Rx 的操作符时,可以多参考一下 Swift 中的操作符,这些都是相同的概念,唯一不同的是,在学习 Rx 的过程中,您需要建立流的概念,1, 2, 3, nil, 4 都是按照时间顺序一个一个发射传递下去的,只是经过过 flatMap
操作后,nil
并没有走下去而已。