Skip to content

Zip

1. 概要

Zip は、複数の Observable ソースの値をインデックス順に組み合わせるファクトリメソッドです。各ソースの 1 番目の値同士、2 番目の値同士…のように対応する位置の値を配列にまとめて発行します。

すべてのソースが現在のインデックスの値を発行するまで待機するため、発行速度の異なるソースでも正しくペアリングされます。いずれかのソースが完了すると、結果の Observable も完了します。

2. シグネチャ

params 配列

csharp
public static Observable<T[]> Zip<T>(params Observable<T>[] sources)

可変長引数で複数のソースを指定します。

csharp
Observable.Zip(sourceA, sourceB, sourceC)

IEnumerable

csharp
public static Observable<T[]> Zip<T>(IEnumerable<Observable<T>> sources)

ソースのコレクションを動的に渡す場合に使用します。

csharp
var sources = new List<Observable<int>> { sourceA, sourceB };
Observable.Zip(sources)

オーバーロードの使い分け

オーバーロード使う場面
Zip<T>(params Observable<T>[])ソース数がコンパイル時に決まっている場合
Zip<T>(IEnumerable<Observable<T>>)ソースを動的に生成・収集する場合

3. マーブルダイアグラム

Zip のマーブルダイアグラム

Zip は各ソースの値をインデックス順にペアリングします。すべてのソースが同じインデックスの値を発行するまで待機し、揃った時点で配列として発行します。いずれかのソースが完了すると結果も完了します。

4. サンプルコード

csharp
using R3;

var letters = new Subject<string>();
var numbers = new Subject<int>();

Observable.Zip(letters, numbers)
    .Subscribe(values => Console.WriteLine($"[{string.Join(", ", values)}]"));

// ※ 上記は同じ型でないと使えないため、同じ型の例で示します
var subject1 = new Subject<int>();
var subject2 = new Subject<int>();

Observable.Zip(subject1, subject2)
    .Subscribe(values => Console.WriteLine($"[{string.Join(", ", values)}]"));

subject1.OnNext(1);       // まだ出力なし(subject2 のインデックス 0 が未到着)
subject1.OnNext(2);       // まだ出力なし
subject2.OnNext(10);      // 出力: [1, 10](インデックス 0 のペア)
subject2.OnNext(20);      // 出力: [2, 20](インデックス 1 のペア)
subject2.OnNext(30);      // まだ出力なし(subject1 のインデックス 2 が未到着)
subject1.OnNext(3);       // 出力: [3, 30](インデックス 2 のペア)

subject1.OnCompleted();   // 結果も完了

5. 補足

オペレーター版との違い

オペレーター版 Zip は、2〜15 個の異なる型のソースを受け取り、resultSelector 関数で結合結果を任意の型に変換できます。この静的ファクトリメソッド版は同じ型のソースのみを対象とし、結果を T[] として返します。