Skip to content

Zip

1. 概要

Zip は、複数の Observable ソースの要素をインデックス順にペアリングし、結合関数で組み合わせた結果を発行するオペレーターです。

各ソースの 1 番目の要素同士、2 番目の要素同士…というように対応する位置の要素を組み合わせます。すべてのソースがその位置の要素を発行するまで結果は生成されず、いずれかのソースが完了すると結果のシーケンスも完了します。

2. シグネチャ

2 つのソースをペアリングする(型付きオーバーロード)

csharp
public static Observable<TResult> Zip<T1, T2, TResult>(
    this Observable<T1> source1,
    Observable<T2> source2,
    Func<T1, T2, TResult> resultSelector)

2 つの異なる型の Observable をインデックス順にペアリングし、resultSelector で結合します。

csharp
source1.Zip(source2, (x, y) => x + y)

3〜15 個のソースをペアリングする(型付きオーバーロード)

csharp
public static Observable<TResult> Zip<T1, T2, T3, TResult>(
    this Observable<T1> source1,
    Observable<T2> source2,
    Observable<T3> source3,
    Func<T1, T2, T3, TResult> resultSelector)

3 個から最大 15 個のソースを型安全にペアリングできます。

csharp
source1.Zip(source2, source3, (x, y, z) => $"{x}-{y}-{z}")

同一型の可変個数ソースをペアリングする(配列 / IEnumerable)

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

同じ型の Observable を任意の個数まとめてペアリングします。結果は各ソースの対応する位置の値を格納した配列 T[] として発行されます。

csharp
Observable.Zip(sourceA, sourceB, sourceC)

overload の使い分け

overload使う場面
2〜15 引数の型付きソース数が固定で、異なる型をペアリングしたい場合
params Observable<T>[]同一型のソースを動的な個数でペアリングしたい場合
IEnumerable<Observable<T>>ソースのコレクションを渡したい場合

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

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

各ソースの同じ位置の要素が揃ったときに、組み合わせた結果が下流へ流れます。先に発行された値はもう一方が追いつくまでバッファされます。

4. サンプルコード

csharp
using R3;

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

numbers.Zip(letters, (n, l) => $"{n}{l}")
    .Subscribe(x => Console.WriteLine(x));

numbers.OnNext(1);        // まだ出力なし(letters が未発行)
numbers.OnNext(2);        // まだ出力なし
letters.OnNext("A");      // 出力: 1A(1 番目同士をペアリング)
letters.OnNext("B");      // 出力: 2B(2 番目同士をペアリング)
letters.OnNext("C");      // まだ出力なし(numbers の 3 番目がまだ)
numbers.OnNext(3);        // 出力: 3C

5. 補足

CombineLatest との違い

CombineLatest は、いずれかのソースが発行するたびに各ソースの最新値を再利用して結果を生成します。Zip は各値を 1 回だけ消費し、インデックス順にペアリングします。

特性ZipCombineLatest
ペアリング方式インデックス順最新値の組み合わせ
値の消費1 回だけ最新値を繰り返し使用
バッファリングありなし

ZipLatest との違い

ZipLatest は、各ソースが前回の組み合わせ以降に新しい値を発行したかどうかを基準にします。中間の値は破棄され、最新値のみが使用されます。Zip はすべての値をバッファして順番にペアリングします。

ファクトリメソッド版との違い

ファクトリメソッド版 Zip は、同じ型の複数ソースを params または IEnumerable で受け取り、結果を T[] として発行します。異なる型のソースを型安全に組み合わせ、結果を任意の型へ変換したい場合は、このオペレーター版を使います。