2012-04-23 186 views
2

我有bool三个(或更多)可观察序列:执行操作

IObservable<bool> a0 = ...; 
IObservable<bool> a1 = ...; 
IObservable<bool> a2 = ...; 

这些序列产生大多false值,但过一段时间有一个true(序列也可以是空的)。我对这些值本身不感兴趣,而是按照true值的顺序。所以,如果a0true,然后a2是真实的,最后a1,我想执行一些动作:

(a0, a2, a1) => ...do something... 

但如果true值出现在另一个命令,我想其他人做一些事情:

(a2, a1, a0) => ...do something else... 
(a0, a1, a2) => ...do something entirely else... 

所以我只对每个序列的第一个true值感兴趣,并且根据它们出现的顺序,我想执行一些操作。

我可以记录每个第一次出现true的时间戳,然后在CombineLatest呼叫中排序,但我有一种感觉,有更好的方法。这种方法的一个问题是我现在依赖记录时间戳的粒度。

+0

他们能任何其他可观察火灾的真实之前再次触发一个'真'?这是一场'滚动'比赛吗,还是三次比赛都开始了? – yamen 2012-04-23 12:42:48

+0

我只对第一个'真正'价值感兴趣。之后,我处理观察员。 – 2012-04-23 12:44:04

+0

我已经根据这个和其他一些天真的假设给出了答案。但是,总体方法应该转化为一些情景。 – yamen 2012-04-23 13:08:16

回答

4

首先,你只需要真值,所以忽略其余的。其次,您可以将每个观察值编码为更多的语义含义(也许是一个字符串?)。第三,你可以合并这些流,等待3个值到达,并根据它们采取行动。

设置:

var a0 = new Subject<bool>(); 
var a1 = new Subject<bool>(); 
var a2 = new Subject<bool>(); 

编码:

var a0t = a0.Where(x => x).Select(x => "a0").Take(1); // thanks Matthew Finlay 
var a1t = a1.Where(x => x).Select(x => "a1").Take(1); 
var a2t = a2.Where(x => x).Select(x => "a2").Take(1); 

合并,并得到后三个值:

var merged = a0t.Merge(a1t).Merge(a2t); 
var message = merged.Buffer(3).Subscribe(x => ProcessMessage(String.Join("", x))); 

,加工部:

public void ProcessMessage(string message) 
{ 
    switch(message) { 
     case "a0a1a2": Console.WriteLine("1"); break; 
     case "a1a2a0": Console.WriteLine("2"); break; 
     case "a2a1a0": Console.WriteLine("3"); break; 
    } 
} 

和测试:

a1.OnNext(true); 
a2.OnNext(true); 
a0.OnNext(true); 
+0

好:)我绝对可以把这个翻译成我的具体情况。 – 2012-04-23 13:10:45

+0

测试它:完美的作品。谢谢! – 2012-04-23 13:37:09

+0

聪明的回答,荣誉。 – BFree 2012-04-23 14:48:48