Nobollel開発者ブログ

Nobollelのエンジニアが、UnityやCocos2d-xの旬な情報・技術を紹介します。

【Reactive Extensions】 IObservableの合成と分岐入門その4

おはこんばんにちは、tsuchimotoです。

今回は前回の第3回に引き続き、UniRxを使ったIObservableの合成と分岐入門の4回目になります。

前回までのリンク

Zipメソッド

Zipメソッドについて説明します。

Zipメソッドは2つの合成元のシーケンスから流れてきた値が2つ揃った時点で初めて、合成後のIObservableのシーケンスに値が流れます。

Zipメソッドのシグネチャは以下になります。

public static IObservable<R> Zip<T, U, R>(
    // 1つ目のシーケンス
    this IObservable<T> first, 
    // 2つ目のシーケンス
    IObservable<U> second, 
    // 合成後のシーケンス
    Func<T, U, R> resultSelector);

Zipメソッドの使用例を以下に示します。

1秒間隔で0, 1, 2の値を発行するIObservableのシーケンスと100, 101, 102の値を発行するIObservableのシーケンスをZipメソッドで合成しています。

// 1秒間隔で0,1,2と発行される
Observable.Interval(TimeSpan.FromSeconds(1)).Take(3)
    // Zipでまとめる
    .Zip(
        // 100, 101と発行される
        Observable.Range(100, 2), 
        // 流れてきた値を元に文字列化
        (l, r) => string.Format("{0}:{1}", l, r))
    // 購読
    .Subscribe(
        s => Debug.Log("OnNext: {0}", s),
        () => Debug.Log("OnCompleted"));

実行結果を以下に示します。

2つの発行された値が1つのシーケンスになって流れてくることが確認できると思います。

ただしここで注意したいのは、1番目のシーケンスから発行された「3」が2番目のシーケンスと揃わないので後続に流れてきません。

OnNext: 0:100
OnNext: 1:101
OnCompleted

CombineLatestメソッド

CombineLatestメソッドについて説明します。

Zipメソッドが両方のIObservableのシーケンスから値が発行されるのを待つのに対してCombineLatestメソッドは、 どちらか一方から値が発行されると、もう一方の最後に発行した値があるか確認し、あればそれを使って後続に値を流します。

このメソッドのシグネチャを以下に示します。

public static IObservable<R> CombineLatest<F, S, R>(
    this IObservable<F> first, 
    IObservable<S> second, 
    Func<F, S, R> resultSelector);

このメソッドのコード例を下記に示します。

先ほどのZipメソッドのコードとほぼ同じでZipメソッドがCombineLatestメソッドになっただけです。

// 1秒間隔で0,1,2と発行される
Observable.Interval(TimeSpan.FromSeconds(1)).Take(3)
    // CombineLatestでまとめる
    .CombineLatest(
        // 100, 101と発行される
        Observable.Range(100, 2), 
        // 流れてきた値を元に文字列化
        (l, r) => string.Format("{0}:{1}", l, r))
    // 購読
    .Subscribe(
        s => Debug.Log("OnNext: {0}", s),
        () => Debug.Log("OnCompleted"));

このコードの実行結果を以下に示します。 始めに「100」が発行された後に2はつ目のシーケンスが発行されないので、後続には流れてきません。 「101」発行後に「0」が発行されて初めて後続に流れてきます。

OnNext: 0:101
OnNext: 1:101
OnNext: 2:101
OnCompleted