Reducing a sequence
缩减队列的操作分为如下几类:
- 过滤与分割操作:减少source sequence(源队列)到一个相同数量元素的队列。
- 集结操作:减少source sequence(源队列)到只有一个元素的队列。
- 折叠操作:将source sequence(源队列)减少为单个元素的标量值。
从标量值(可参考https://msdn.microsoft.com/en-us/library/94z15h2c.aspx)创建的可观测物队列被定义为anamorphism(合成变质),或“unfold”(展开)。我们可以把从T到IObservable<T>的anamorphism(合成变质)想象成一个“unfold”(展开),或进入monad(单细胞生物)。在这种情况下(和本书中的大部分情况下),monad(单细胞生物)为IObservable<T>。与之相反的操作是catamorphism(变化)或fold(折叠),fold(折叠)的另外一些流行的名字是“reduce”(减少)、“accumulate”(积聚)和“inject”(注入)。
Where
对队列进行筛选是一个很常见的操作,而最常见的过滤操作是Where子句。在RX中你可以使用Where子句,也就是Where扩展方法,它的签名如下:
注意,名为source的参数和返回类型是相同的。这将使接口变得流畅,可以大量的使用RX和其他LINQ代码。在下面的例子中,我们将使用Where子句来过滤所有从Range队列中产生的偶数值:
Output:
0
2
4
6
8
Completed
Where操作是标准的LINQ操作之一,为了保持本书的一致性,我们将继续使用扩展方法这个称呼。
Distinct and DistinctUntilChanged
相信很多人都熟悉Where对应IEnumerable<T>的扩展方法,有些还知道Distinct方法。在RX中,Distinct方法一样对可观测物队列有效,它只会从接受到的值中传递之前没有出现过的值。
Output:
1
distinct.OnNext(1)
2
distinct.OnNext(2)
3
distinct.OnNext(3)
1
1
4
distinct.OnNext(4)
subject.OnCompleted()
distinct.OnCompleted()
在上面的例子中,subject 传递了1三次,而distinct过滤了重复的1,只输出了1次。
Distinct方法还有不同的重载允许你用专门的方式确定一个item是否明确(是否已经被赋值)。一种方法是提供一个方法来返回一个用于比较的不同值。下面的例子使用了一个自定义类中的属性来定义一个值是否明确:
除了可以提供keySelector方法,还有一个接受一个IEqualityComparer<T>实例的重载,它在你有一个自定义的实现可以用于比较你的类型T的实例时非常有用。最后有一个重载,接受一个keySelector和一个IEqualityComparer<TKey>的实例。注意,在这种情况下的相等比较器是针对TKey,而不是你的类型T。
DistinctUntilChanged与Distinct略微不同,这个方法仅在与上一个值不同时才会显示值。重用第一个Distinct的例子,注意输出的变化:
Output:
1
distinct.OnNext(1)
2
distinct.OnNext(2)
3
distinct.OnNext(3)
1
distinct.OnNext(1)
1
4
distinct.OnNext(4)
subject.OnCompleted()
distinct.OnCompleted()
这一次1被distinct输出了2次,DistinctUntilChanged方法只有在与前一个值重复时才会忽略,更早的则不会。
IgnoreElements
IgnoreElements扩展方法是一个古怪的小工具,允许你接收OnCompleted或OnError消息。我们也可以通过一个总是返回false的断言(Func类型委托参数)的Where方法来实现同样的效果。
Output:
subject.OnNext(1)
subject.OnNext(2)
subject.OnNext(3)
subject.OnCompleted()
noElements.OnCompleted()
在上面的例子中,noElements只接收了onCompleted消息。我们也可以用Where实现相同的效果:
在我们结束Where和IgnoreElements方法的介绍之前,我们来回顾一下最后一行代码。在函数式编程中下划线“_”通常用来表示一个被忽略的参数。对上面的例子来说它是适用的,我们忽略它并且总是返回false。
暂无关于此日志的评论。