簡體   English   中英

合並重疊的可觀察流,但采用最新值

[英]Combine overlapping observable streams but take most recent values

我已經嘗試過用Rx合並流的用例。 我有3個流輸出值:

S1: ----1----2----3----4----5-----6
S2: ----a---------c---------d------
S3: ---------x---------y----------z

我想合並(壓縮)流1和2以及1和3,邏輯是2和3永遠不能同時輸出值。

因此,所需的輸出為:

1,a
2,x
3,c
4,y
5,d
6,z

但是實際發生的是:

1,a
1,x
2,c
2,y
3,d
3,z

關於如何獲得所需輸出的任何線索?

碼:

Subject<int> s1 = new Subject<int>();
Subject<string> s2 = new Subject<string>();
Subject<string> s3 = new Subject<string>();

var zip1 = s1.Zip(s2, (x, y) => {
    return new Tuple<int, string>(x, y);
});

var zip2 = s1.Zip(s3, (x, y) => {
    return new Tuple<int, string>(x, y);
});

zip1.Subscribe(Console.WriteLine, () => Console.WriteLine("Completed"));
zip2.Subscribe(Console.WriteLine, () => Console.WriteLine("Completed"));

s1.OnNext(1);
s2.OnNext("a");

s1.OnNext(2);
s3.OnNext("x");

s1.OnNext(3);
s2.OnNext("c");

s1.OnNext(4);
s3.OnNext("y");

s1.OnNext(5);
s2.OnNext("d");

s1.OnNext(6);
s3.OnNext("z");

對於您擁有的每個流s2和s3,您可以創建一個Subject ,訂閱原始流,然后在等待下一個s1值之后將該值傳遞給新的Subject

var zip1 = new Subject<Tuple<int, string>>();
s2.Subscribe(async value =>
{
    var other = await s1.FirstAsync();
    zip1.OnNext(Tuple.Create(other, value));
});

var zip2 = new Subject<Tuple<int, string>>();
s3.Subscribe(async value =>
{
    var other = await s1.FirstAsync();
    zip2.OnNext(Tuple.Create(other, value));
});

您已經聲明要管理流的時序,以便從s1為合並的其他流的每個值產生一個值。 如果您確實做到這一點,那會沒事的。 如果從s1產生的多個值在另一個流中沒有任何對應的值,則將被忽略,並且如果從其他流組合得到的多個值在s1沒有對應的值,則將重復從s1產生的下一個值。

還有一個更人為設計的選項,但是在值之間的時間安排上更加靈活。 這種方法是首先將每個流投影到具有該值但與其他流區分開的值中。 然后可以合並流,並用s1壓縮,然后可以創建多個流,以過濾出每個特定流的值。 然后需要將這些投影回原始值。

var zip = s2.Select(s => Tuple.Create(1, s))
    .Merge(s3.Select(s => Tuple.Create(2, s)))
    .Zip(s1, Tuple.Create);

var zip1 = zip.Where(pair => pair.Item1.Item1 == 1)
    .Select(pair => Tuple.Create(pair.Item2, pair.Item1.Item2));
var zip2 = zip.Where(pair => pair.Item1.Item1 == 2)
    .Select(pair => Tuple.Create(pair.Item2, pair.Item1.Item2));

如果您實際上不需要單獨的流,而只想將輸出復制為單個流,則實際上簡單得多:

var output = s1.Zip(s2.Merge(s3), Tuple.Create);
output.Subscribe(Console.WriteLine, () => Console.WriteLine("Completed"));

這不僅僅是這樣做的情況嗎?

var query =
    s1.Zip(s2.Merge(s3),
        (x, y) => new Tuple<int, string>(x, y));

鑒於問題中提供了您的代碼,我得到了這個結果:

結果

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM