タコさんブログ

プログラミングメモと小言

RxSwift 入門 その3

Transforming Observables

RxSwift 入門 その2 - タコさんブログの続き。
今回は、RxSwiftプレイグラウンドの Transforming Observables の項。
この項では、Observableから送信されるアイテム(イベント)を変換するオペレータについて説明してある。

変換に関するオペレータ

以下、プレイグラウンドに説明してある変換に関するオペレータ。

  • map
  • flatMap
  • scan

この他にも、以下の変換に関するオペレータがある。

  • buffer
  • window

map (a.k.a. select)

mapオペレータはObservableによって送信された各アイテム(イベント)に関数を適用することによって、アイテムを変換する。
RxJavaではSelectになっている。

下の例では、map で Int -> UnicodeScalar に変換している。

// ストリームを生成
let stream = (65..<70).toObservable()
_ = stream
  .map { x in
    UnicodeScalar(x)
  }
  .subscribe {
    print($0)
  }

この出力は、

Next(A)
Next(B)
Next(C)
Next(D)
Next(E)
Completed

このマーブルダイアグラムは以下のように表せられる。

---6---6---6---6---6|
   5   6   7   8   9|
   ↓ map
---A---B---C---D---E|

ここで、

---65---66---67---68---69|

の数字の二桁めを以下のように2段めに記述した。

---6---6---6---6---6|
   5   6   7   8   9|

flatMap

Observableによって送信されたアイテム(イベント)をObservablesに変換し、その後、それらから送信されるアイテムを1つのObservableへ変換(フラットに)する。

下の例では、1〜29のシーケンス値をAのシーケンス、Bのシーケンス、...とZまで繰り返し、27以降は空のシーケンスに変換し、これらを1つのA〜Zのシーケンスに変換している。

let stream = (1..<30).toObservable()
_ = stream
  .flatMap { (x: Int) -> Observable<UnicodeScalar> in
    if case (1..<27) = x {
      return Observable.just(UnicodeScalar(x + 64))
    } else {
      return Observable.empty()
    }
  }
  .subscribe {
    print($0)
}

この出力は、

Next(A)
Next(B)
Next(C)
Next(D)
... // 略
Next(X)
Next(Y)
Next(Z)
Completed

このマーブルダイアグラムは以下のように表せられる。

-1-2 ... -2-2-2-2|
          6 7 8 9|
 A|
  B|
...
          Z|
            |
              |
                |
↓ flatMap
-A-B- ... -Z----|

scan

Observableによって送信された各アイテム(イベント)に関数を逐次適用し、そして、それぞれの連続値を送信する。

下の例では、0をアキュムレータの初期値とし、0〜3までの値を足している。

let stream = Observable.of(0, 1, 2, 3)
_ = stream
  .scan(0) { acum, elem in
    acum + elem
  }
  .subscribe {
    print($0)
}

この出力は、

Next(0)
Next(1)
Next(3)
Next(6)
Completed

このマーブルダイアグラムは以下のように表せられる。

-0-1-2-3|
↓ scan
-0-1-3-6|

参考URL