RxJS の Operators (9) - Conditional and Boolean Operators

この記事は [bouzuya's RxJS Advent Calendar 2015](http://www.adventar.org/calendars/1200) の 11 日目かつ RxJS Advent Calendar 2015 の 11 日目です。

# はじめに

今日は [ReactiveX の Conditional and Boolean Operators](http://reactivex.io/documentation/operators.html#conditional) について [RxJS の API ドキュメント](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/doc/api/core/observable.md)を読んだりサンプルコードを書いたりしていきます。

また [RxJS 4.0.7](https://github.com/Reactive-Extensions/RxJS/tree/v4.0.7) を対象にしています。

## `Observable.prototype.every`

- [ReactiveX - All operator](http://reactivex.io/documentation/operators/all.html)
- [`Observable.prototype.every` API Document](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/doc/api/core/operators/every.md)
- [`Observable.prototype.every` Source Code](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/src/core/linq/observable/every.js)

ReactiveX では All ですが、RxJS では `every` です。

`Array.prototype.every` と同様にすべての値が条件を満たしたときに `onNext(true)` します。ひとつでも違えば、その時点で `onNext(false)` し `onCompleted` します。

```js
import { Observable } from 'rx';

Observable
  .from([1, 2, 3, 4])
  .do(value => console.log(`do: ${value}`))
  .every(value => value < 3)
  .subscribe(
    value => console.log(`onNext: ${value}`),
    error => console.log(`onError: ${error}`),
    () => console.log('onCompleted')
  );
// do: 1
// do: 2
// do: 3
// onNext: false
// onCompleted
```

あえて `false` になる例を。途中で打ち切っているのが分かるように `do` をはさんでいます。

## `Observable.amb` / `Observable.prototype.amb`

- [ReactiveX - Amb operator](http://reactivex.io/documentation/operators/amb.html)
- [`Observable.amb` API Document](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/doc/api/core/operators/amb.md)
- [`Observable.amb` Source Code](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/src/core/linq/observable/amb.js)
- [`Observable.prototype.amb` API Document](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/doc/api/core/operators/ambproto.md)
- [`Observable.prototype.amb` Source Code](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/src/core/linq/observable/ambproto.js)

複数の `Observable` を取り、最初に値を流した `Observable` の値を次に流します。

API ドキュメントによると `amb` は ambiguous の意味だそうです。

`Observable.prototype.amb` は自身ともうひとつの `Observable` を取り、`Observable.amb` と同様に、最初のひとつを選んで利用します。

```js
import { Observable } from 'rx';

Observable
  .amb(
    Observable.timer(500).map(() => '500'),
    Observable.timer(300).map(() => '300')
  )
  .subscribe(
    value => console.log(`onNext: ${value}`),
    error => console.log(`onError: ${error}`),
    () => console.log('onCompleted')
  );
// onNext: 300
// onCompleted
```

## `Observable.prototype.includes`

- [ReactiveX - Includes operator](http://reactivex.io/documentation/operators/contains.html)
- [`Observable.prototype.includes` API Document](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/doc/api/core/operators/includes.md)
- [`Observable.prototype.includes` Source Code](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/src/core/linq/observable/includes.js)

ReactiveX では Contains ですが、RxJS では削除されており includes になっています。

指定した要素が含まれていれば `true` をなければ `false` を `onNext` します。

```js
import { Observable } from 'rx';

Observable
  .from([1, 2, 3])
  .includes(2)
  .subscribe(
    value => console.log(`onNext: ${value}`),
    error => console.log(`onError: ${error}`),
    () => console.log('onCompleted')
  );
// onNext: true
// onCompleted
```

ちなみに `Observable.prototype.indexOf` もあります。

## `Observable.prototype.defaultifempty`

- [ReactiveX - DefaultIfEmpty operator](http://reactivex.io/documentation/operators/defaultifempty.html)
- [`Observable.prototype.defaultifempty` API Document](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/doc/api/core/operators/defaultifempty.md)
- [`Observable.prototype.defaultifempty` Source Code](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/src/core/linq/observable/defaultifempty.js)

`onCompleted` のタイミングで一度も `onNext` されていない場合に `defaultValue` を流します。`defaultValue` はデフォルトで `null` です。下記の例では `123` を指定しています。

```js
import { Observable } from 'rx';

Observable
  .empty()
  .defaultIfEmpty(123)
  .subscribe(
    value => console.log(`onNext: ${value}`),
    error => console.log(`onError: ${error}`),
    () => console.log('onCompleted')
  );
// onNext: 123
// onCompleted
```

## `Observable.prototype.sequenceEqual`

- [ReactiveX - SequenceEqual operator](http://reactivex.io/documentation/operators/sequenceequal.html)
- [`Observable.prototype.sequenceEqual` API Document](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/doc/api/core/operators/sequenceequal.md)
- [`Observable.prototype.sequenceEqual` Source Code](https://github.com/Reactive-Extensions/RxJS/blob/v4.0.7/src/core/linq/observable/sequenceequal.js)

ふたつの `Observable` で前から順に `onNext` の値を比較してすべて一致すれば `true` を流します。

```js
import { Observable } from 'rx';

Observable
  .from([1, 2, 3])
  .sequenceEqual(
    Observable
      .from([1, 2, 3])
      .delay(100)
  )
  .subscribe(
    value => console.log(`onNext: ${value}`),
    error => console.log(`onError: ${error}`),
    () => console.log('onCompleted')
  );
// onNext: true
// onCompleted
```

上記の通り、タイミングがずれても (`delay(100)`) 、流れてくる値が同じなら `true` になります。

# おわりに

ReactiveX の Conditional and Boolean Operators を見ていきました。この区分の意図はあまりよくわかりません。

リスト上は `skipUntil` / `skipWhile` / `takeUntil` / `takeWhile` があったのですが、以前触れたので割愛しました。