首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >直到在Rx.Net

直到在Rx.Net
EN

Stack Overflow用户
提问于 2019-11-07 16:41:34
回答 1查看 1.1K关注 0票数 2

我有两个事件流: 1.鼠标拖放事件流(拖动开始.拖头..。拖曳开始..。拖动结束) 2.按键事件流(a‘a’.'b‘.“c”..。德‘)

我需要合并成一个流,它只包含来自第二个流的事件(所以只包含键按下),但是它需要过滤掉在拖放开始和拖放结束之间发生的所有键按,除了最后一个。

所以如果消息来源是这样的:

代码语言:javascript
复制
... Start ............... End .............. Start .............. End

代码语言:javascript
复制
...........'a'...'b'...'c'.......'d'...'e'..........'f'....'g'.......

结果应该是这样:

代码语言:javascript
复制
...........................'c'...'d'...'e'..........................'g'

在Rx.net中使用C#是否可能出现这种情况?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-11-08 16:01:07

答案是肯定的。先回答,然后解释:

代码语言:javascript
复制
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;
    }

}

然后,给定一个IObservable<T>表示您的值,一个IObservable<bool>表示拖放开始和停止的位置(真正的意义是拖放-启动和假意义的拖放结束),您可以这样称呼它:

代码语言:javascript
复制
var throttledStream= valueStream.GatedDebounce(gateStream);

解释

为了更好地理解它,让我们抛出Publish调用,并将其分解为几个部分:

第一件,

代码语言:javascript
复制
source
    .Window(gating.Where(b => b), _ => gating.Where(b => !b))
    .SelectMany(o => o.LastAsync())

这个Window函数意味着,每当门控发出true时,我们就启动一个可观察到的子集(或窗口),并且在门控发出false时结束该窗口。在该窗口中,如果存在最后一项,我们将选择它。这将只在窗口关闭时发出。

第二件,

代码语言:javascript
复制
source
    .Window(gating.Where(b => !b), _ => gating.Where(b => b))
    .Merge() //Equivalent to .SelectMany(o => o) if you prefer

这个Window函数的作用正好相反:每当门控发出false时,就启动一个窗口;当门控发出true时,就结束它。当它到达时,我们从那个窗口发射出所有的东西。

将这两者与Merge结合起来,您就可以得到90%的解决方案。其余:

  • .StartWith(false)指的是确保我们在一开始启动可观察窗口时打开一个窗口,否则会丢失第一个门项之前发生的值。
  • DistintUntilChanged()是一种廉价的方法,可以确保我们的门是t、f、t、f,而不是一行中的两个相同值,这将导致两个同时打开的窗口。
  • Publish调用是防止多个订阅的良好做法。你可以在这里的其他问答节目中找到更好的解释。
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58753360

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档