简体   繁体   中英

Perform action based on order of events in observable sequences

I have three (or more) observable sequences of bool :

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

These sequences generate mostly false values but once in a while there is a true (the sequences can also be empty). I'm not interested in the values themselves but rather in the order of the true values. So if a0 is true , then a2 is true and finally a1 , I'd like to perform some action:

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

But if the true values appear in another order, I'd like to do something else:

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

So I'm only interested in the first true value of each sequence and depending on the order in which they occur, I'd like to perform some action.

I could record the timestamp of each first occurrence of true and then sort in a CombineLatest call, but I have a feeling there is a better way. One problem with this approach is that I am now dependent on granularity of recorded timestamps.

Firstly, you only need the true values so ignore the rest. Second, you can encode each observable into a more semantic meaning (perhaps a string?). Third, you can then merge these streams, wait for 3 values to arrive, and act based on them.

Set up:

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

Encoding:

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);

Merge and get after three values:

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

The processing section:

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;
    }
}

And test:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM