Skip to content

ZipLatest

1. 概要

ZipLatest は、すべてのソースが前回の発行以降に新しい値を発行したときに、各ソースの最新値を組み合わせて結果を生成するオペレーターです。

Zip のように値をインデックス順にバッファするのではなく、各ソースの最新値のみを保持します。すべてのソースが「新しい値を持っている」状態になったときに 1 回だけ結果を発行し、使用された値はリセットされます。

2. シグネチャ

2 つのソースの最新値を組み合わせる(型付きオーバーロード)

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

2 つのソースが両方とも新しい値を持っているときに、resultSelector で結合した結果を発行します。

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

3〜15 個のソースの最新値を組み合わせる(型付きオーバーロード)

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

3 個から最大 15 個のソースを型安全に結合できます。

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

同一型の可変個数ソースを結合する(配列 / IEnumerable)

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

同じ型の Observable を任意の個数まとめて結合します。結果は各ソースの最新値を格納した配列 T[] として発行されます。

csharp
Observable.ZipLatest(sourceA, sourceB, sourceC)

overload の使い分け

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

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

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

すべてのソースが新しい値を発行した時点で、各ソースの最新値を組み合わせた結果が下流へ流れます。結果が発行されると値はリセットされ、再びすべてのソースが新しい値を発行するのを待ちます。

4. サンプルコード

csharp
using R3;

var subject1 = new Subject<int>();
var subject2 = new Subject<string>();

subject1.ZipLatest(subject2, (num, str) => $"{num}-{str}")
    .Subscribe(x => Console.WriteLine(x));

subject1.OnNext(1);       // まだ出力なし(subject2 が未発行)
subject1.OnNext(2);       // まだ出力なし(最新値が 2 に更新される)
subject2.OnNext("A");     // 出力: 2-A(両方が新しい値を持つ)
subject1.OnNext(3);       // まだ出力なし(subject2 の新しい値を待つ)
subject2.OnNext("B");     // 出力: 3-B
subject2.OnNext("C");     // まだ出力なし(subject1 の新しい値を待つ)
subject1.OnNext(4);       // 出力: 4-C

5. 補足

Zip との違い

Zip はすべての値をバッファしてインデックス順にペアリングするため、中間の値も漏れなく消費されます。ZipLatest は中間の値を破棄し、常に最新値のみを使用します。

特性ZipLatestZip
値の保持最新値のみすべてバッファ
中間値の扱い破棄保持して順番に消費
メモリ使用量一定増加する可能性あり

CombineLatest との違い

CombineLatest は、いずれかのソースが発行するたびに結果を生成します。ZipLatest はすべてのソースが新しい値を発行するまで結果を生成しません。

特性ZipLatestCombineLatest
発行条件すべてのソースが新しい値を発行いずれかのソースが発行
値のリセット発行後にリセットリセットしない
発行頻度低い(全ソースの更新を待つ)高い(どれか 1 つの更新で発行)

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

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