3

Rx ベースの変更追跡ソリューションの場合、監視可能なシーケンスの最初で最新のアイテムを取得できるオペレーターが必要です。

次のマーブル ダイアグラムを生成する Rx 演算子をどのように記述すればよいでしょうか (注: 角かっこは項目を並べるためだけに使用されています...これをテキストで表現する最善の方法がわかりません):

     xs:---[a  ]---[b  ]-----[c  ]-----[d  ]---------|
desired:---[a,a]---[a,b]-----[a,c]-----[a,d]---------| 
4

3 に答える 3

5

@Wilka と同じ名前を使用すると、以下の拡張機能を使用できます。

public static IObservable<TResult> FirstAndLatest<T, TResult>(this IObservable<T> source, Func<T,T,TResult> func)
{
    var published = source.Publish().RefCount();
    var first = published.Take(1);        
    return first.CombineLatest(published, func);
}

必ずしも を返すとは限りませんTupleが、結果にセレクター関数を渡すオプションを提供することに注意してください。これにより、基礎となるプライマリ オペレーション ( CombineLatest) との整合性が保たれます。これは明らかに簡単に変更できます。

使用法 (結果のストリームにタプルが必要な場合):

Observable.Interval(TimeSpan.FromSeconds(0.1))
          .FirstAndLatest((a,b) => Tuple.Create(a,b))
          .Subscribe(Console.WriteLine);
于 2012-07-27T20:43:30.733 に答える
2

これを試して:

public static IObservable<Tuple<T, T>> FirstAndLatest<T>(
    this IObservable<T> source)
{
    return
        source
            .Take(1)
            .Repeat()
            .Zip(source, (x0, xn) => Tuple.Create(x0, xn));
}

シンプルですね。


または、基になるソースを共有する代わりに、これを試してください。

public static IObservable<Tuple<T, T>> FirstAndLatest<T>(
    this IObservable<T> source)
{
    return
        source.Publish(
            s =>
                s.Take(1)
                .Repeat()
                .Zip(s, (x0, xn) => Tuple.Create(x0, xn)));
}

おっと!これをスクラッチします。うまくいきません。基本的に、最新の値のペアを生成し続けます。このような公開は機能しません。オリジナルの実装が最適です。

于 2012-07-28T05:46:16.840 に答える
1

これを行うにはもっと良い方法があると思いますが (Do の使用は嫌いです)、次のような演算子を作成することもできます。

public static IObservable<Tuple<T, T>> FirstAndLatest2<T>(this IObservable<T> source)
{
    return Observable.Defer(() => {
        bool hasFirst = false;
        T first = default(T);

        return source
            .Do(item =>
            {
                if (!hasFirst)
                {
                    hasFirst = true;
                    first = item;
                }
            })
            .Select(current => Tuple.Create(first, current));
    });
}

次に、次のように使用します。

Observable.Interval(TimeSpan.FromSeconds(0.1))
    .FirstAndLatest()
    .Subscribe(Console.WriteLine);
于 2012-07-27T20:09:22.777 に答える