RxSwift 之过滤操作
在前面的基础之上接下来我会介绍一些常用的函数和实用技巧。首先,本文将会介绍那些用于对 next 事件进行过滤的操作。这些过滤操作类似于 Swift 标准库中的 filter 操作。它能在我们开始真正进行业务处理前先把那些不符合条件的过滤掉,而且这种函数式编程的范式也能开阔我们的思维。
Ignore 过滤
RxSwift 中最简单直接的过滤操作就是 ignoreElements 了。该操作会屏蔽所有的 next 事件,只会将注意力放在 error 和 completed 事件上。如下图所示,在整个生命周期中可观察对象的所有 next 都被过滤。
示例代码:
let strikes = PublishSubject<String>()let disposeBag = DisposeBag()strikes.ignoreElements().subscribe { _ inprint("You're out!")}.addDisposableTo(disposeBag)strikes.onNext("X")
strikes.onNext("X")
strikes.onNext("X")strikes.onCompleted()/* 打印结果
You're out!
*/复制代码
不过相比于残暴的全部过滤,有时候我们可能只是需要过滤某些特定的事件。例如,我们可以通过 elementAt 对特定索引号 next 进行过滤。下图演示了只响应第二个 next 事件的 elementAt 操作。
与之相应的代码为:
let strikes = PublishSubject<String>()let disposeBag = DisposeBag()strikes.elementAt(2).subscribe(onNext: { str inprint(str)}).addDisposableTo(disposeBag)strikes.onNext("1")
strikes.onNext("2")
strikes.onNext("3")strikes.onCompleted()/* 打印结果
3
*/复制代码
上面两个操作最后针对的 next 事件最多只会有一个,但是大多数时候我们其实需要筛选出一组符合条件的 next 事件。下图演示的就是使用 filter 筛选数据小于 3 的操作。
图示对应代码如下:
let strikes = PublishSubject<Int>()let disposeBag = DisposeBag()strikes.filter{ $0 < 3 }.subscribe(onNext: { num inprint("\(num)")}).addDisposableTo(disposeBag)strikes.onNext(1)
strikes.onNext(2)
strikes.onNext(3)
strikes.onNext(4)
strikes.onNext(5)strikes.onCompleted()/* 打印结果
1
2
*/复制代码
Skip 过滤
除了忽略操作外,另一个常见的过滤就是跳过操作了。在所有的跳过操作中,最简单的就属 skip 了。通过设定参数,我们就能和简单实现跳过指定个数的事件。例如,下图久演示跳过前两个事件的操作。
let strikes = PublishSubject<Int>()let disposeBag = DisposeBag()strikes.skip(2).subscribe(onNext: { num inprint("\(num)")}).addDisposableTo(disposeBag)strikes.onNext(1)
strikes.onNext(2)
strikes.onNext(3)
strikes.onNext(4)
strikes.onNext(5)strikes.onCompleted()/* 打印结果
3
4
5
*/复制代码
当然除了跳过指定索引号的事件之外,我们依旧通过 skipWhile 我们能够实现类似 filter 类似的操作。只不过 filter 会过滤整个生命周期内的符合条件的事件,而 skipWhile 在找到第一个不符合跳过操作的事件之后就不再工作。例如,下图 skipWhile 的条件是数据为奇数就跳过,但是当数据 2 执行之后 数据 3 虽然也是奇数但是不会在跳过。所以严格意义上来说 skipWhile 可能有点歧义,实际是它会跳过所有符合条件的事件,直到找到第一个能执行事件后就不再生效。
下面是跳过偶数的 skipWhile 代码:
let strikes = PublishSubject<Int>()let disposeBag = DisposeBag()strikes.skipWhile{ num innum % 2 == 0}.subscribe(onNext: { num inprint("\(num)")}).addDisposableTo(disposeBag)strikes.onNext(2)
strikes.onNext(2)
strikes.onNext(3)
strikes.onNext(4)
strikes.onNext(5)strikes.onCompleted()/* 打印结果
3
4
5
*/复制代码
到目前为止,上面的过滤操作都是基于一些静态条件。如果现在你需要根据其它可观察对象实例的行为进行过滤判断怎么办呢?所以接下来将会介绍涉及多实例的动态判断,其中最常见的就是 skipUntil 操作。该操作过程如下图,上面两行表示可观察对象的生命周期而最下面的表示观察者,直到第二行的可观察对象发送数据后第三行的观察者才能接受到第一行发送的数据。
图示对应代码:
let strikes = PublishSubject<String>()
let trigger = PublishSubject<String>()let disposeBag = DisposeBag()strikes.skipUntil(trigger).subscribe(onNext: { print($0)}).addDisposableTo(disposeBag)strikes.onNext("1")trigger.onNext("X")strikes.onNext("2")
strikes.onNext("3")strikes.onCompleted()/* 打印结果
2
3
*/复制代码
Take 过滤
这是一组与 Skip 相反的过滤操作。这组操作中最基础的操作为 take ,该操作的过程完全与 skip 相反。下图演示了 take(2) 操作的过程,它只会对前两个事件进行响应而忽略后面的事件。
上图对应代码:
let strikes = PublishSubject<String>()let disposeBag = DisposeBag()strikes.take(2).subscribe(onNext: { print($0)}).addDisposableTo(disposeBag)strikes.onNext("1")
strikes.onNext("2")
strikes.onNext("3")strikes.onCompleted()/* 打印结果
1
2
*/复制代码
除此之外,skipWhile 也有对应的 Take 操作 takeWhile ,两者的代码结构几乎一致只不过前者是跳过操作而后者则是响应操作。不过这里我不准备介绍 takeWhile 操作(可以自己动手试下),而是介绍 takeWhile 变种 takeWhileWithIndex。其实函数名已经表明了该操作的主要功能,在 takeWhile 的基础上会加上索引 index 参数。因为有时候我们除了需要通过 value 进行过滤判断外,索引 index 也可能是一个判断维度。下图就展示了 takeWhileWithIndex 简单使用示例,对于 value 和 index 值小于 1 的事件全部跳过。
图示对应代码:
let strikes = PublishSubject<Int>()let disposeBag = DisposeBag()strikes.takeWhileWithIndex { integer, index ininteger > 1 && index > 1}.subscribe(onNext: { print( "\($0)")}).addDisposableTo(disposeBag)strikes.onNext(1)
strikes.onNext(2)
strikes.onNext(3)strikes.onCompleted()/* 打印结果
3
*/复制代码
其实 Skip 组中同样存在与 takeWhileWithIndex 相对的 skipWhileWithIndex ,感兴趣可以自己检验一下。接下来我们介绍 Take 组中的最后一个操作 takeUntil 。同样地该操作是 skipUntil 的反操作,直到另一个实例对象触发后该实例对象的观察者才会停止响应。下图就是 takeUntil 操作的一个简单示例,作为观察者第三行会一直响应第一行可观察对象发送的数据,直到第二行对象触发后才停止。
对应代码:
let strikes = PublishSubject<String>()
let trigger = PublishSubject<String>()let disposeBag = DisposeBag()strikes.takeUntil(trigger).subscribe(onNext: { print($0)}).addDisposableTo(disposeBag)strikes.onNext("1")
strikes.onNext("2")trigger.onNext("X")strikes.onNext("3")strikes.onCompleted()/* 打印结果
1
2
*/复制代码
Distinct 过滤
最后本文将介绍 Distinct 过滤操作 distinctUntilChanged 。对于观察者来说,有时可观察对象可能在某段时间内连续发生相同的数据。假设这些数据与 UI 相关的话,那么这里就存在不必要的刷新操作了。所以我们有必要对过滤这些连续的相同数据,减少不必要的响应操作。下图就是一个简单的示例,图中我们过滤掉了相同的后续数据,只会对第一个作出响应。
对应示例代码:
let strikes = PublishSubject<String>()let disposeBag = DisposeBag()strikes.distinctUntilChanged().subscribe(onNext: { print($0)}).addDisposableTo(disposeBag)strikes.onNext("1")
strikes.onNext("2")
strikes.onNext("2")
strikes.onNext("3")strikes.onCompleted()/* 打印结果
1
2
3
*/复制代码
总结
本文在前面的基础上通过图示和代码介绍了主要的过滤操作。掌握好这些操作有利于我们最大化的发挥 RxSwift 功力。当然文中的代码都非常简单,所以我希望你在实际编程中不断磨练。
原文地址
RxSwift 之过滤操作相关推荐
- [翻译]ElasticSearch官方文档-执行查询和过滤操作
本文翻译自:www.elastic.co/guide/en/el- 本文是Elasticsearch的入门文档,将会介绍ElasticSearch中的查询操作和过滤操作. 执行查询 现在我们已经看到了 ...
- 二、使用Stream流的方式完成过滤操作
package stream01;import java.util.ArrayList; import java.util.stream.Stream;/*** 使用Stream流的方式完成过滤操作* ...
- 「SQL数据分析系列」4.过滤操作
来源 | Learning SQL Generate, Manipulate, and Retrieve Data, Third Edition 作者 | Alan Beaulieu 译者 | Li ...
- Scala中过滤操作filter与filterNot函数
Scala中有很多实现不同过滤需求的方法,与过滤操作相关的几个常用函数还包括exists和find. 其中,exists方法判断是否存在满足给定条件的元素,find方法返回第一个满足条件的元素. fi ...
- 【SQL必知必会笔记(3)】SELECT语句的WHERE子句数据过滤操作
上个笔记主要介绍了利用SELECT语句检索单个/多个/所有列,并利用DISTINCT关键字检索具有唯一性的值.利用LIMIT/OFFSET子句限制结果:以及利用ORDER BY子句排序检索出的数据,主 ...
- Rxjava操作符之过滤操作
前言: 本文将介绍以下过滤类操作符(基于Rxjava2.0): filter ofType take takeLast first firstOrError last lastOrError skip ...
- Hbase shell过滤操作
Get 和 Scan 操作都可以使用过滤器来设置输出的范围,类似于 SQL 里面的 Where 查询条件.使用 show_filters 命令可以查看当前 HBase 支持的 过滤器类型. show_ ...
- elasticsearch中对于空字符串的过滤操作
## 在项目的一个需求中,需要对ELK中的数据进行聚合统计的操作,这里因为是用Java进行开发,所以需要涉及到相应的api的使用.因为之前从来没碰过ELK之类的环境,刚拿到这个问题的时候自己还是有点懵 ...
- Filtering 过滤操作
filter( ) - 过滤数据 takeLast( ) - 只发射最后的N项数据 last( ) - 只发射最后的一项数据 lastOrDefault( ) - 只发射最后的一项数据,如果Obser ...
最新文章
- LigerUI——天外飞仙
- Servlet--05--HttpServletRequest; HttpServletResponse
- Android-上传图片(二)_HttpClient
- sizeof 计算struct大小
- 第一批鸿蒙系统手机型号,鸿蒙2.0第一批机型名单正式披露!花粉却感叹:华为不够厚道!...
- linux执行jar包命令没有主清单熟悉,jar命令成功完成 java -jar 命令却提示“没有主清单属性”!...
- java中所有的类都继承于_Java中所有的类都是通过直接或间接地继承( )类得到的...
- java基础---Math工具类
- NB-IOT连接移动onenet平台流程
- python脚本文件格式_Python 基础语法_Python脚本文件结构
- linux 时间戳计数器,使用TSC(时间戳计数器)计算时间
- 独角访谈 | 去中心化交易所领军人物–Loi Luu
- 智能优化算法:未来搜索算法-附代码
- VS C++ memcpy() memset()不明确报错
- 创建虚拟机并加载镜像文件
- python requests接收chunked编码问题
- Android 切换双卡数据链接__2019.11.22
- plc无法跟计算机通信,无法与PLC通信
- 资料分享:送你一本《C#区块链编程》电子书!
- python pymysql连接池_杂项之pymysql连接池