Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我可以使用什么运算符返回两个序列的“重叠”?_C#_System.reactive - Fatal编程技术网

C# 我可以使用什么运算符返回两个序列的“重叠”?

C# 我可以使用什么运算符返回两个序列的“重叠”?,c#,system.reactive,C#,System.reactive,我有一个流IObservable eventStream,它表示键盘输入skeyup或KeyDown的流。通过应用窗口操作符,我可以隔离保持输入的持续时间: public static IObservable<InputEvent> WhileHeld(this IObservable<InputEvent> source, String key) { var k = source.Where(i => i.Key == key); return s

我有一个流IObservable eventStream,它表示键盘输入skeyup或KeyDown的流。通过应用窗口操作符,我可以隔离保持输入的持续时间:

public static IObservable<InputEvent> WhileHeld(this IObservable<InputEvent> source, String key) {
    var k = source.Where(i => i.Key == key);
    return source.Window(k.Press(), _ => k.Release()).Switch().Where(i => i.Key != key);
}
我想应用一个运算符来查找这两个序列之间的重叠,如下图所示

K=事件类型,其中。是媒体,是发布 i=事件流 C=eventStream.whilheldctrl S=eventStream.whilheldshift r=结果流 大理石:

K |--.---.-.-.-'-'---.-.-.-'-'---.-.-'-.-.-.-'
i |--a---C-S-b-S-C---C-S-c-C-S---C-S-S-d-S-e-C-

C |--------S-b-S-------S-c---------S-S-d-S-e---
S |----------b-----------c-C---------------e-C

r |----------b-----------c-----------------e---
是否存在这样的运营商?或者它是如何组成的

编辑:

为了帮助可视化实际事件流,我意识到上面的大理石图有点复杂。以下是我的事件流测试代码:

eventStream.Pump("a", EventType.Down); // should not propagate

eventStream.Pump("ctrl", EventType.Down);
eventStream.Pump("shift", EventType.Down);
eventStream.Pump("b", EventType.Down); // should propagate
eventStream.Pump("shift", EventType.Up);
eventStream.Pump("ctrl", EventType.Up);

eventStream.Pump("ctrl", EventType.Down);
eventStream.Pump("shift", EventType.Down);
eventStream.Pump("c", EventType.Down); // should propagate
eventStream.Pump("ctrl", EventType.Up);
eventStream.Pump("shift", EventType.Up);

eventStream.Pump("ctrl", EventType.Down);
eventStream.Pump("shift", EventType.Down);
eventStream.Pump("shift", EventType.Up);
eventStream.Pump("d", EventType.Down); // should not propagate
eventStream.Pump("shift", EventType.Down);
eventStream.Pump("e", EventType.Down); // should propagate
eventStream.Pump("ctrl", EventType.Up);

到目前为止,我最接近的是:

var ctrlShift = Observable.CombineLatest(ctrlHeld, shiftHeld)
    .SelectMany(list =>
        {
            if (list.Any(o => o != list[0]))
                return Observable.Empty<InputEvent>();
            else
                return Observable.Return(list[0]);
        });

它确实有用,但有点难看。如果有比这更简洁、更富有表现力的答案,我会接受它。

注:我会在电脑前测试/修改一次

我认为您可以通过GroupJoin获得重叠窗口行为,如下所示:

var ctrlShift = ctrlHeld.GroupJoin(
        shiftHeld,
        e => eventStream.Key("ctrl").Release(),   // "left duration" selector
        e => eventStream.Key("shift").Release(),  // "right duration" selector
        (a,b) => b.Key(a.Key).Press())
    .Switch();
但我永远无法单独从视觉上正确理解GroupJoin语法,因此很可能不是这样……基本上,我的想法是:

从ctrlHeld中的事件开始,直到发生ctrl释放 从换档中的事件开始到换档释放发生 选择重叠b,仅按两个窗口中的按钮 将这些嵌套的观测值展平并返回 编辑:进一步考虑,您可能可以在持续时间中重用窗口选择器

var ctrlShift = ctrlHeld.GroupJoin(
        shiftHeld,
        e => ctrlHeld,   // "left duration" selector
        e => shiftHeld,  // "right duration" selector
        (a,b) => b.Key(a.Key).Press())
    .Switch();
啊哈,我知道有一个链接解释了这一点:


我最终提出的解决方案提供了x.whilheldctrl.whilheldshift的合成语法。诀窍是传入从原始源派生的IObservable,而不是字符串,然后打开它:

public static IObservable<InputEvent> WhileHeld(this IObservable<InputEvent> source, IObservable<InputEvent> held) {
    return source.Window(held.Press(), _ => held.Release()).Switch();
}

...

var x = InputStream.Where(i => i.Key == "X");
var shift = InputStream.Where(i => i.Key == "Shift");
var ctrl = InputStream.Where(i => i.Key == "Ctrl");

// gets all key presses of X while shift and control are held
var ctrlShiftX = x.WhileHeld(shift).WhileHeld(ctrl);

这意味着将捕获按住的键的第一次和最后一次按键,但我认为这不一定是件坏事。

您不能只使用r=eventStream.whilheldCtrl.whilheldshift吗?我希望它这么简单!如果有人能想到一个whilehold操作符,它的性能与上面的一样,那么我会接受这一点——遗憾的是,这不起作用——它接受上面的d,当r=eventStream.whileholdshift.whileholdctrl反转为r=eventStream.whileholdshift.whilewaldctrl时,它什么也不接受——那么你大概想要的是如果ctrl+shift+key=>key?我想要问题中描述的行为,我不知道如何解释你的评论…哈-足够公平;我想尝试重新表述您的问题:您希望结果流是在按住shift和control键的同时按下的键?
public static IObservable<InputEvent> WhileHeld(this IObservable<InputEvent> source, IObservable<InputEvent> held) {
    return source.Window(held.Press(), _ => held.Release()).Switch();
}

...

var x = InputStream.Where(i => i.Key == "X");
var shift = InputStream.Where(i => i.Key == "Shift");
var ctrl = InputStream.Where(i => i.Key == "Ctrl");

// gets all key presses of X while shift and control are held
var ctrlShiftX = x.WhileHeld(shift).WhileHeld(ctrl);