Kob*_*ari 3 reactive-programming system.reactive rx.net
我有 2 个事件流: 1. 鼠标拖放事件流(拖动开始...拖动结束...拖动开始...拖动结束) 2.按键事件流('a' ... ' b' .... 'c' .... 'd')
我需要合并到一个仅包含第二个流中的事件(因此仅包含按键)的流中,但它需要过滤掉拖动开始和拖动结束之间发生的所有按键(最后一个除外)。
所以如果来源是这样的:
... Start ............... End .............. Start .............. End
Run Code Online (Sandbox Code Playgroud)
和
...........'a'...'b'...'c'.......'d'...'e'..........'f'....'g'.......
Run Code Online (Sandbox Code Playgroud)
结果应该是这样的:
...........................'c'...'d'...'e'..........................'g'
Run Code Online (Sandbox Code Playgroud)
在 C# 中使用 Rx.net 可以实现类似的功能吗?
答案是肯定的。先回答,再解释:
public static class X
{
public static IObservable<T> GatedDebounce<T>(this IObservable<T> source, IObservable<bool> gating)
{
var finalStream = gating
.StartWith(false)
.DistinctUntilChanged()
.Publish(_gating => source.Publish(_source => Observable.Merge(
_source
.Window(_gating.Where(b => b), _ => _gating.Where(b => !b))
.SelectMany(o => o.LastAsync()),
_source
.Window(_gating.Where(b => !b), _ => _gating.Where(b => b))
.Merge()
)));
return finalStream;
}
}
Run Code Online (Sandbox Code Playgroud)
然后,给定一个IObservable<T>表示您的值的值,以及一个IObservable<bool>表示拖动开始和停止的位置(true 表示拖动开始, false 表示拖动结束),您可以这样称呼它:
var throttledStream= valueStream.GatedDebounce(gateStream);
Run Code Online (Sandbox Code Playgroud)
解释:
为了更好地理解它,让我们扔掉这些Publish调用,并将其分成几部分:
第 1 块,
source
.Window(gating.Where(b => b), _ => gating.Where(b => !b))
.SelectMany(o => o.LastAsync())
Run Code Online (Sandbox Code Playgroud)
这个Window函数意味着调用意味着每当门控发出 true 时我们就启动一个可观察的子集(或窗口),并在门控发出 false 时结束该窗口。从该窗口中,我们选择最后一项(如果存在)。仅当窗口关闭时才会发出此消息。
第 2 块,
source
.Window(gating.Where(b => !b), _ => gating.Where(b => b))
.Merge() //Equivalent to .SelectMany(o => o) if you prefer
Run Code Online (Sandbox Code Playgroud)
此Window函数执行相反的操作:每当 gating 发出 false 时启动一个窗口,并在 gating 发出 true 时结束它。当一切到达时,我们都会从那个窗口发出它。
将这两者放在一起Merge,您就可以完成 90% 的解决方案。其余的部分:
.StartWith(false)是为了确保我们在您最初启动可观察对象时打开一个窗口,否则第一个门控项之前发生的值将丢失。DistintUntilChanged()是一种廉价的方法,可以确保我们的门是 t, f, t, f,并且永远不会有两个连续的相同值,这会导致两个窗口同时打开。Publish调用是防止重复订阅的好习惯。您可以在此处的其他一些问答中找到更好的解释。| 归档时间: |
|
| 查看次数: |
1514 次 |
| 最近记录: |