Flatten sequence of numeric values by threshold with rxjs
使用rxjs,我得到了一个可观察到的浮点数序列。现在,我想过滤出流中较小的变化,并且仅当它比先前发出的值大某个数量时才发出一个值。
换句话说:始终发出序列中的第一个值。然后,每个发出的(=未过滤的)值应至少比先前发出的值大delta。任何不符合该条件的值都将被过滤。
我已经想出了一个解决方案,可以如上所述完成我想要的工作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | var obs = Rx.Observable.create(function(observer) { /* ... */ }); var last; obs.map(function(value) { if (last === undefined) { last = value; return value; } else { var threshold = 0.5, delta = Math.abs(last - value); if (delta > threshold) { last = value; return value; } else { return undefined; } } }). filter(function(value) { return value !== undefined; }); |
我是rxjs和反应式编程的新手,我认为上述解决方案过于复杂。更重要的是,它违反了反应式编程的原则,即不将状态保存在组合管道之外。但是我这样做是因为我正在通过
如何解决此问题并以反应方式进行?
您可以使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | var filtered = obs.scan({}, function (acc, value) { if (acc.value !== undefined) { var threshold = 0.5, change = Math.abs(acc.value - value); if (change < threshold) { return { value: acc.value, isValid: false }; } } return { value: value, isValid: true }; }) .filter(function (acc) { return acc.isValid; }) .map(function (acc) { return acc.value; }); |
我知道这已经回答了,但是如果您发现自己经常这样做,则可以自己做。只是吐口水,因为它是一个有趣的实用程序:
1 2 3 4 5 6 7 8 9 10 11 12 | Observable.prototype.maxThreshold = function(threshold, selector) { var last = null; return this.filter(function(x) { var n = selector ? selector(x) : x; var delta = Math.abs(n - last); if(last === null || delta > threshold) { last = n; return true; } return false; }); }); |
可用于以下用途:
1 2 3 4 | streamOfNumbers.maxThreshold(0.5). subscribe(function(x) { console.log(x); }); |
或
1 2 3 4 | streamOfObjects.maxThreshold(0.5, function(x) { return x.value; }). subscribe(function(x) { console.log(x); }); |