3

別のオブザーバブルの値に基づいてオブザーバブルをフィルタリングする方法を見つけようとしています。たとえば、時間 x と y の間のイベントのみを受信したいとします。タイマーの値に基づいてオブザーバブルをフィルタリングできますか?

4

2 に答える 2

1

Brandonが述べたように、イベント ストリームを組み合わせる方法はたくさんあります。

とのリアクティブ結合Observable.Joinは非常に汎用的なツールですが、演算子の Rx 組み込みライブラリのかなりの部分が、別のフィルターに基づくフィルター処理をサポートできる方法でストリームを結合します。

SelectBrandon の+Switchテクニック (私から +1)が本当に好きです。将来の使用のためにそれをファイルしました!

これは、ソース ストリームを開始時間と終了時間にフィルター処理するという前述の問題に直接取り組むアプローチです。Select+に比べて次のような利点がありますSwitch

  • ソース ストリームのすべてのイベントのフィルター条件をチェックすることを回避します。
  • 「空の」ストリームが不要になります。
  • ソースに一度だけサブスクライブします。
  • OnCompleted()ソースストリームが続く限り続くのではなく、終了時間に達するとすぐに送信します。

これは実際には、Observable.Windowオペレーターの特定のオーバーロードに要約されますが、順を追って説明します。

Window基本的な考え方は、開始時間に開き、終了時間に閉じる を適用してソース ストリームをフィルタリングすることです。

xs最初に、1 秒のパルスと開始時間と終了時間のサンプル ソース ストリーム ( ) を作成します。

var xs = Observable.Interval(TimeSpan.FromSeconds(1));

var startTime = DateTime.Now + TimeSpan.FromSeconds(5);    
var endTime = DateTime.Now + TimeSpan.FromSeconds(8);

簡潔にするために、startTimebeforeであることを確認していないことに注意してくださいendTime。次に、ウィンドウを開くストリームと、ウィンドウを閉じるストリームを作成します。

var start = Observable.Timer(startTime);
var end = Observable.Timer(endTime);

最後に、 を使用してソース ストリームをフィルタリングしますObservable.Window。このオペレーターの出力は、ストリームのストリーム ( IObservable<IObservable<T>>) です。各サブストリームは新しいウィンドウです。

使用するオーバーロードは、イベントが新しいウィンドウの開始をマークするストリームと、ウィンドウの開始をトリガーしたイベントを指定して終了ストリームを提供するファクトリ関数を受け入れます。

Timer ストリームを使用すると、開始時刻に作成され、終了時刻に閉じられるウィンドウが 1 つだけあることがわかります。

以下を使用して、ストリームのストリームを平坦化しますObservable.Merge

var filtered = xs.Window(start, _ => end).Merge();

これをサブスクライブすると、次のようになります。

filtered.Subscribe(Console.WriteLine);

期待どおり、次の出力が得られます。

4
5
6

繰り返しますが、この問題を解決するには、 を使用するだけでなく、非常に多くの方法がありますWindow。また、このソリューションを簡単に拡張して、たとえば、複数のウィンドウをサポートすることもできます (開店時間ストリームと閉店時間ストリーム ファクトリを使用することにより)。

于 2013-12-27T14:42:19.570 に答える