【Unity】【UniRx】フィルタリング系のオペレータまとめ

UniRxにおいてストリームに流れてきた値をフィルタイングするオペレータをまとめました。

Where

条件式に合うものだけ流します。

var subject        = new Subject<int>();

subject
    .Where(x => x > 10)
    .Subscribe(x => Debug.Log(x));

subject.OnNext(1); // 流れない
subject.OnNext(100); // 流れる
subject.OnNext(10); // 流れない

Distinct

一度流れた値は流しません。

var subject        = new Subject<int>();

subject
    .Distinct()
    .Subscribe(x => Debug.Log(x));

subject.OnNext(1); // 流れる
subject.OnNext(1); // 流れない
subject.OnNext(2); // 流れる
subject.OnNext(1); // 流れない

DistinctUntilChanged

直前に同じ値が流れていたら流しません。

var subject        = new Subject<int>();

subject
    .DistinctUntilChanged()
    .Subscribe(x => Debug.Log(x));

subject.OnNext(1); // 流れる
subject.OnNext(1); // 流れない
subject.OnNext(2); // 流れる
subject.OnNext(1); // 流れる

First

初めに流れた値だけ流し、OnCompletedします。
ただし、一度も値が流れずにOnCompleted()が呼ばれるとエラーになります。

var subject        = new Subject<int>();

subject
    .First()
    .Subscribe(x => Debug.Log(x), () => Debug.Log("completed"));

subject.OnNext(1); // 流れる
subject.OnNext(1); // 流れない
subject.OnNext(2); // 流れない

FirstOrDefault

初めに流れた値だけ流し、OnCompletedします。
Firstと違って一度も値が流れずにOnCompleted()が呼ばれるてもエラーにならず、
OnNext()でデフォルト値を流してOnCompleted()します。

var subject        = new Subject<int>();

subject
    .FirstOrDefault()
    .Subscribe(x => Debug.Log(x), () => Debug.Log("completed"));

// 一度も値を流さずにOnCompleted()してもエラーにならない
subject.OnCompleted();

Last

OnCompletedの時点で最新の値を流します。
ただし、一度も値が流れずにOnCompleted()が呼ばれるとエラーになります。

var subject        = new Subject<int>();

subject
    .Last()
    .Subscribe(x => Debug.Log(x), () => Debug.Log("completed"));

subject.OnNext(1); // 流れない
subject.OnNext(1); // 流れない
subject.OnNext(2); // 流れる
subject.OnCompleted();


#### LastOrDefault
OnCompletedの時点で最新の値を流します。    
Lastと違って一度も値が流れずにOnCompleted()が呼ばれるてもエラーにならず、  
OnNext()でデフォルト値を流してOnCompleted()します。

var subject = new Subject();

subject .LastOrDefault() .Subscribe(x => Debug.Log(x), () => Debug.Log("completed"));

// 一度も値を流さずにOnCompleted()してもエラーにならない subject.OnCompleted();




Single

初めに流れた値だけを流します。
Firstと違い2個目が流れたらエラーになります。
また1個も流れずにOnCompleted()してもエラーになります。

var subject        = new Subject<int>();

subject
    .Single()
    .Subscribe(x => Debug.Log(x), () => Debug.Log("completed"));

subject.OnNext(1); // 流れる
subject.OnNext(1); // エラー

SingleOrDefault

初めに流れた値だけを流します。
Singleと同様2個目が流れたらエラーになります。
ただし1個も流れずにOnCompleted()してもエラーにはなりません。

var subject        = new Subject<int>();

subject
    .SingleOrDefault()
    .Subscribe(x => Debug.Log(x), () => Debug.Log("completed"));

// 一度も値を流さずにOnCompleted()してもエラーにならない
subject.OnCompleted();

Skip

最初からx個だけ流さずに、それ以降は流します。

var subject        = new Subject<int>();

subject
    .Skip(2)
    .Subscribe(x => Debug.Log(x), () => Debug.Log("completed"));

subject.OnNext(1); // 流れない
subject.OnNext(1); // 流れない
subject.OnNext(1); // 流れる

SkipWhile

流れてくる値が条件式を満たしている間は流さずに、一つでも満たしてからは流します。

var subject        = new Subject<int>();

subject
    .SkipWhile(x => x < 2)
    .Subscribe(x => Debug.Log(x), () => Debug.Log("completed"));

subject.OnNext(1); // 流れない
subject.OnNext(10); // 流れる
subject.OnNext(1); // 流れる

SkipUntil

引数のObservableが流れるまでは値を流さずに、それ以降は流します。

var subject        = new Subject<int>();
var subject2        = new Subject<int>();

subject
    .SkipUntil(subject2)
    .Subscribe(x => Debug.Log(x), () => Debug.Log("completed"));

subject.OnNext(1); // 流れない
subject.OnNext(10); // 流れない
subject2.OnNext(0);
subject.OnNext(1); // 流れる

Take

最初からx個だけ流して、それ以降は流しません。

var subject        = new Subject<int>();

subject
    .Take(2)
    .Subscribe(x => Debug.Log(x), () => Debug.Log("completed"));

subject.OnNext(1); // 流れる
subject.OnNext(2); // 流れる
subject.OnNext(3); // 流れない

TakeWhile

流れてくる値が条件式を満たしている間は流して、一つでも満たしてからは流しません。

var subject        = new Subject<int>();

subject
    .TakeWhile(x => x < 2)
    .Subscribe(x => Debug.Log(x), () => Debug.Log("completed"));

subject.OnNext(1); // 流れる
subject.OnNext(10); // 流れない
subject.OnNext(1); // 流れない

TakeUntil

引数のObservableが流れるまでは値を流して、それ以降は流しません。

var subject        = new Subject<int>();
var subject2        = new Subject<int>();

subject
    .TakeUntil(subject2)
    .Subscribe(x => Debug.Log(x), () => Debug.Log("completed"));

subject.OnNext(1); // 流れる
subject.OnNext(10); // 流れる
subject2.OnNext(0);
subject.OnNext(1); // 流れない

IgnoreElements

OnNext()をすべて流しません。

var subject        = new Subject<int>();

subject
    .IgnoreElements()
    .Subscribe(x => Debug.Log(x), () => Debug.Log("completed"));

subject.OnNext(1); // 流れない
subject.OnNext(10); // 流れない
subject.OnCompleted(); // 流れる