2012-04-23 185 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