4

私の目標はおそらく大理石の図で最も簡単に説明できます。xsとysの2つのオブザーバブルがあります。rsという名前のObservableを返したい。

xs --x---x---x---x-------x---x---x-
      \           \       \
ys ----y-----------y---y---y-------
       |           |       |
rs ----x-----------x-------x-------
       y           y       y

したがって、xsの後にysが続く場合にのみ起動する必要があることを除いて、CombineLatestに似たものが必要です。そのパターンの外側にある追加のxsまたはysは、出力をトリガーしないため、破棄する必要があります。

CombineLatest、Zip、またはAnd / Then /必要なことを実行せず、より複雑な結合構造を指定する方法が見つからない場合。

4

3 に答える 3

3

結局、Joinを使用しました。

var rs = xs.Join(ys, 
                 _ => xs.Merge(ys),
                 _ => Observable.Empty<Unit>(),
                 Tuple.Create);

これは、Joinの仕組みを説明する優れた記事です:http: //blogs.microsoft.co.il/blogs/bnaya/archive/2012/04/04/rx-join.aspx

于 2012-11-11T20:08:58.027 に答える
3

このような質問には、テストシナリオを提供することが非常に役立ちます。あなたはあなたが望むものの素晴らしい小さな大理石の図を与えました、それからそれをテストケースに変換することは本当に簡単です。次に、他のフォーラムリーダーは、テストコードを取得し、アイデアを実装して、要件を満たしているかどうかを知ることができます。

[Test]
public void Should_only_get_latest_value_from_Y_but_not_while_x_produes()
{
    //            11111111112222222222333
    //   12345678901234567890123456789012
    //xs --x---x---x---x-------x---x---x-
    //      \           \       \
    //ys ----y-----------y---y---y-------
    //       |           |       |
    //rs ----x-----------x-------x-------
    //       y           y       y


    var testScheduler = new TestScheduler();
    //            11111111112222222222333
    //   12345678901234567890123456789012
    //xs --x---x---x---x-------x---x---x-
    var xs = testScheduler.CreateColdObservable(
        new Recorded<Notification<char>>(3, Notification.CreateOnNext('1')),
        new Recorded<Notification<char>>(7, Notification.CreateOnNext('2')),
        new Recorded<Notification<char>>(10, Notification.CreateOnNext('3')),
        new Recorded<Notification<char>>(15, Notification.CreateOnNext('4')),
        new Recorded<Notification<char>>(23, Notification.CreateOnNext('5')),
        new Recorded<Notification<char>>(27, Notification.CreateOnNext('6')),
        new Recorded<Notification<char>>(31, Notification.CreateOnNext('7')));

    //            11111111112222222222333
    //   12345678901234567890123456789012
    //ys ----y-----------y---y---y-------
    var ys = testScheduler.CreateColdObservable(
        new Recorded<Notification<char>>(5, Notification.CreateOnNext('A')),
        new Recorded<Notification<char>>(17, Notification.CreateOnNext('B')),
        new Recorded<Notification<char>>(21, Notification.CreateOnNext('C')),
        new Recorded<Notification<char>>(25, Notification.CreateOnNext('D')));


    //Expected :
    //Tick  x   y
    //5     1   A
    //17    4   B
    //25    5   D
    var expected = new[]
    {
        new Recorded<Notification<Tuple<char, char>>>(5, Notification.CreateOnNext(Tuple.Create('1', 'A'))),
        new Recorded<Notification<Tuple<char, char>>>(17, Notification.CreateOnNext(Tuple.Create('4', 'B'))),
        new Recorded<Notification<Tuple<char, char>>>(25, Notification.CreateOnNext(Tuple.Create('5', 'D')))
    };

    var observer = testScheduler.CreateObserver<Tuple<char, char>>();

    //Passes HOT, fails Cold. Doesn't meet the requirements due to Timeout anyway.
    //xs.Select(x => ys.Take(1)
    //                    .Timeout(TimeSpan.FromSeconds(0.5),
    //                            Observable.Empty<char>())
    //                    .Select(y => Tuple.Create(x, y))
    //    )
    //    .Switch()
    //    .Subscribe(observer);

    //Passes HOT. Passes Cold
    xs.Join(ys,
            _ => xs.Merge(ys),
            _ => Observable.Empty<Unit>(),
            Tuple.Create)
        .Subscribe(observer);

    testScheduler.Start();

    //You may want to Console.WriteLine out the two collections to validate for yourself.

    CollectionAssert.AreEqual(expected, observer.Messages);
}

PSちなみに答えのためのMergeの素晴らしい使用法。

于 2012-11-14T17:43:34.393 に答える
0

ダイアグラムを別の言い方で述べると、各xは、yの前に追加のxを付けずに最初のyを取る必要があります。それらの最初の要件は示唆しています。その時点で、があります。2番目の要件と最初の2つのポイントによって生成されるタイプは。すべてをまとめると、図を次のように一致させることができるはずです。Take(1)IObservable<IObservable<...>>Switch

var rs = xs.Select(x => ys.Take(1)
                          .Select(y => Tuple.Create(x, y))
                  )
           .Switch()
于 2012-11-10T05:54:54.790 に答える