過去記事インデックス
- Reactive Extensions再入門 その1
- Reactive Extensions再入門 その2「IObservableインターフェースとIObserverインターフェース」
- Reactive Extensions再入門 その3「IObservableのファクトリメソッド」
- Reactive Extensions再入門 その4「Timer系のファクトリメソッド」
- Reactive Extensions再入門 その5「HotとCold」
- Reactive Extensions再入門 その6「HotなIObservableを作成するファクトリ」
- Reactive Extensions再入門 その7「LINQスタイルの拡張メソッド」
- Reactive Extensions再入門 その8「SkipとTakeメソッド」
- Reactive Extensions再入門 その9「Skip + Take + Repeat = ドラッグ」
- Reactive Extensions再入門 その10「Doメソッド」
- Reactive Extensions再入門 その11「Catchメソッド」
- Reactive Extensions再入門 その12「Finallyメソッドとリソース解放」
- Reactive Extensions再入門 その13「最後の値を取得するLatestとMostRecentメソッド」
- Reactive Extensions再入門 その14「Nextメソッド」
- Reactive Extensions再入門 その15「To*****系メソッド」
- Reactive Extensions再入門 その16「最大、最少、平均を求めるメソッド」
- Reactive Extensions再入門 その17「集計するメソッド」
- Reactive Extensions再入門 その18「CountメソッドとLongCountメソッド」
- Reactive Extensions再入門 その19「AnyメソッドとAllメソッド」
- Reactive Extensions再入門 その20「GroupByメソッドでグルーピングしてみよう」
- Reactive Extensions再入門 その21「GroupByUntilメソッド」
- Reactive Extensions再入門 その22「単一の値を取得するメソッド」
- Reactive Extensions再入門 その23「重複を排除するメソッド」
- Reactive Extensions再入門 その24「単一の値を取得するメソッド その2」
- Reactive Extensions再入門 その25「値をまとめるBufferメソッド」
- Reactive Extensions再入門 その26「値をまとめるWindowメソッド」
- Reactive Extensions再入門 その27「時間でフィルタリング?Sampleメソッド」
- Reactive Extensions再入門 その28「落ち着いたら流すThrottleメソッド」
- Reactive Extensions再入門 その29「値を指定した時間だけ遅延させるDelayメソッド」
- Reactive Extensions再入門 その30「もう待ちきれない!を表現するTimeoutメソッド」
- Reactive Extensions再入門 その31「時間に関する情報を付与するTimestampとTimeIntervalメソッド」
- Reactive Extensions再入門 その32「型変換を行うCastとOfTypeメソッド」
- Reactive Extensions再入門 その33「シーケンスの最後を起点にSkipとTake」
- Reactive Extensions再入門 その34「ダメなら次の人!を実現するOnErrorResumeNextメソッド」
- Reactive Extensions再入門 その35「駄目ならやり直す!を実現するRetryメソッド」
- Reactive Extensions再入門 その36「ColdからHotへ!Publishメソッドと参照カウンタ?RefCountメソッド」
- Reactive Extensions再入門 その37「ColdからHotへ!その他のPublish系メソッド」
- Reactive Extensions再入門 その38「ColdからHotへ!その他のPublish系メソッド2」
- Reactive Extensions再入門 その39「Subject系クラス」
- Reactive Extensions再入門 その40「IObservableの合成はじめました」
- Reactive Extensions再入門 その41「どんどん合成するよ」
- Reactive Extensions再入門 その42「StartWithメソッドとJoinメソッド」
はじめに
今回はGroupJoinメソッドについてみていきます。使いどころは、まだわからないですが動きはとりあえず把握しておきましょう!
GroupJoinメソッド
ここでは、GroupJoinメソッドについて説明します。GroupJoinメソッドは、2つのIObservable
public static IObservable<TResult> GroupJoin<TLeft, TRight, TLeftDuration, TRightDuration, TResult>( this IObservable<TLeft> left, IObservable<TRight> right, Func<TLeft, IObservable<TLeftDuration>> leftDurationSelector, Func<TRight, IObservable<TRightDuration>> rightDurationSelector, Func<TLeft, IObservable<TRight>, TResult> resultSelector);
Joinメソッドと、ほぼ同じシグネチャですが、resultSelectorデリゲートの引数に違いがあります。resultSelectorデリゲートの第二引数がJoinメソッドではTRight型だったのに対してGroupJoinメソッドではIObservable
// センサー名 var sensors = new Subject<string>(); // センサーが受信する値 var values = new Subject<int>(); // 値のリセット用Subject var valueReset = new Subject<Unit>(); sensors.GroupJoin( values, // センサーは有効期限無し _ => Observable.Never<Unit>(), // センサーの値はvalueResetのOnNextで無効に出来る _ => valueReset, // センサーの名前と、センサーが受け取った値の現在の合計値を発行するLogにして後続に流す (l, r) => new { Name = l, Log = r.Scan((x, y) => x + y) }) .Subscribe( sensor => { // Logを表示する sensor .Log .Subscribe(i => Console.WriteLine("{0}: {1}", sensor.Name, i)); }, // 完了 () => Console.WriteLine("OnCompleted")); // センサーを2つ登録 Console.WriteLine("sensors.OnNext(sensor1)"); sensors.OnNext("sensor1"); Console.WriteLine("sensors.OnNext(sensor2)"); sensors.OnNext("sensor2"); // 値を3つ発行 Console.WriteLine("values.OnNext(100)"); values.OnNext(100); Console.WriteLine("values.OnNext(10)"); values.OnNext(10); Console.WriteLine("values.OnNext(1)"); values.OnNext(1); // センサーの値を一旦リセット Console.WriteLine("valueReset.OnNext()"); valueReset.OnNext(Unit.Default); // 新しいセンサーを追加 Console.WriteLine("sensors.OnNext(sensor3)"); sensors.OnNext("sensor3"); // 値を3つ発行 Console.WriteLine("values.OnNext(1)"); values.OnNext(1); Console.WriteLine("values.OnNext(2)"); values.OnNext(2); Console.WriteLine("values.OnNext(3)"); values.OnNext(3); // 終了 Console.WriteLine("values.OnCompleted()"); values.OnCompleted(); Console.WriteLine("sensors.OnCompleted()"); sensors.OnCompleted();
コードのイメージはセンサーと、センサーが受信した値の合計値をリアルタイムで表示するプログラムです。センサーが受信する値は任意のタイミング(valueReset変数のOnNext)でリセットできるようにしています。このメソッドの実行結果を以下に示します。
sensors.OnNext(sensor1) sensors.OnNext(sensor2) values.OnNext(100) sensor1: 100 sensor2: 100 values.OnNext(10) sensor1: 110 sensor2: 110 values.OnNext(1) sensor1: 111 sensor2: 111 valueReset.OnNext() sensors.OnNext(sensor3) values.OnNext(1) sensor1: 112 sensor2: 112 sensor3: 1 values.OnNext(2) sensor1: 114 sensor2: 114 sensor3: 3 values.OnNext(3) sensor1: 117 sensor2: 117 sensor3: 6 values.OnCompleted() sensors.OnCompleted() OnCompleted
sensor1とsensor2は、発行された値の合計を全て保持していることが確認できますが、valueResetのOnNextを呼んだ後に追加したsensor3は、途中からの値の合計しか集計していないことが確認できます。