我有一个Observable发出数字(整数,双精度数,BigDecimal实际上并不重要)。我有一个在可观察的合成时间定义的阈值。换句话说,阈值在可观察的生命周期内不会改变。
我需要过滤出与阈值内最后通过的值不同的值。或改写它:仅当值与上一个传递的值相差超过阈值时,才将其传递给下游。
示例将对其进行更好的解释:
Source observable values:
[5, 4, 7, 9, 15, 14, 13, 12, 11, 7, 3, 2, 1]
Filetered values with threshold = 3 :
[5, 9, 15, 11, 7, 3]
为更好地说明,例如,假设它是温度读数。我只想过滤那些温度变化超过3度的值。第一个值始终会通过并用作要比较的初始值。例如,如果第一个温度读数为21摄氏度,并且在一个小时内每个后续读数都在[18..24]中,则这些值都不应向下游传递。但是,一旦越过这些界限,就应该通过并创建新的界限以进行比较。
问题是:如何仅使用RxJava运算符执行此操作?还是除了将状态存储在rx管道之外(以易失性或原子引用或任何其他同步状态,细节都没有关系)之外,别无其他方法吗?
答案 0 :(得分:5)
您可以结合使用scan
和distinctUntilChanged
仅通过RX运算符来实现此目的。
scan
允许您访问上一个和下一个值,从而可以与给定的阈值进行比较。
如果未达到阈值,则可以发出前一个值。
distinctUntilChanged
然后可以用来减少重复排放。
在科特林,它看起来像下面的样子:
val threshold = 3
val list = listOf(5, 4, 7, 9, 15, 14, 13, 12, 11, 7, 3, 2, 1)
return Observable.fromIterable<Int>(list)
.scan { previous: Int, next: Int ->
val difference = abs(next - previous)
when {
difference > threshold -> next
else -> previous
}
}.distinctUntilChanged()