【UniRx】メッセージをフィルタリングするオペレータ #94
前回の成果
ファクトリメソッド系のオペレータについて学んだ。
今回やること
今回はメッセージのフィルタのオペレータについてまとめます。
- 前回の成果
- 今回やること
- メッセージのフィルタ
- 1度流れたものは流さない
- 値が前回と異なる場合に流す
- 指定した時間値が流れてこなかったら最後のonNextを流す
- 最初は値を流し、指定した時間は流さないを繰り返す
- 最初のonNextのみ通し、onCompletedを発行
- onCompletedを発行した時点での最後の値を発行
- OnNextが2回以上流れたら、onErrorを発行
- 指定した数だけ流す
- 指定した条件を満たしている間は流し、一度でも満たしていないものが来たら以降は流さない
- 指定したObservableのonNextが発行されるまで流す
- 指定した数流さず、それ以降は流す
- 指定した条件を満たしている間は流さず、一度でも満たしているものが来たら以降は流す
- 指定したObservableのonNextが発行されるまで流さない
- OnErrorかonCompletedのみ流し、onNextは流さない
- 参考サイト様
メッセージのフィルタ
流れてきたメッセージをフィルタリングするメソッド群になります。
条件を満たすものを流す
Where
/// <summary> /// 条件を満たすものを流す /// </summary> private void ExcuteWhere() { Subject<int> subject = new Subject<int>(); subject .Where(x => x > 10) .Subscribe(x => { Debug.Log("Where : " + x); }); // 流れない subject.OnNext(1); // 流れない subject.OnNext(10); // 流れる subject.OnNext(100); }
結果
1度流れたものは流さない
Distinct
/// <summary> /// 1度流れたものは流さない /// </summary> private void ExcuteDistinct() { Subject<int> subject = new Subject<int>(); subject .Distinct() .Subscribe(x => { Debug.Log("Distinct : " + x); }); // 流れる subject.OnNext(1); // 流れない subject.OnNext(1); // 流れる subject.OnNext(0); // 流れない subject.OnNext(1); // 流れない subject.OnNext(0); }
結果
値が前回と異なる場合に流す
DistinctUntilChanged
/// <summary> /// 値が前回と異なる場合に流す /// </summary> private void ExcuteDistinctUntilChanged() { Subject<int> subject = new Subject<int>(); subject .DistinctUntilChanged() .Subscribe(x => { Debug.Log("DistinctUntilChanged : " + x); }); // 流れる subject.OnNext(1); // 流れない subject.OnNext(1); // 流れる subject.OnNext(0); // 流れる subject.OnNext(1); // 流れる subject.OnNext(0); }
結果
指定した時間値が流れてこなかったら最後のonNextを流す
秒の代わりにフレームを指定する、ThrottleFrameも存在します。
Throttle
/// <summary> /// 指定した時間値が流れてこなかったら最後のonNextを流す /// </summary> private void ExcuteThrottle() { this.UpdateAsObservable() .Where(_ => Input.anyKeyDown) .Throttle(TimeSpan.FromSeconds(2)) .Subscribe(_ => { Debug.Log("Throttle"); }); }
結果
上の例の場合ですと、何かキーを押してから2秒間何もキーを押さないとメッセージが発行されます。
最初は値を流し、指定した時間は流さないを繰り返す
秒の代わりにフレームを指定する、ThrottleFirstFrameも存在します。
ThrottleFirst
/// <summary> /// 最初は値を流し、指定した時間は流さないを繰り返す /// </summary> private void ExcuteThrottleFirst() { this.UpdateAsObservable() .ThrottleFirst(TimeSpan.FromSeconds(1)) .Subscribe(_ => { Debug.Log("ThrottleFirst"); }); }
結果
最初のonNextのみ通し、onCompletedを発行
値を一度も流さずにonCompletedを呼ぶとエラーになってしまいます。
値を一度も流さずにonCompletedを呼びたい場合はFirstOrDefaultを使用してください。
First
/// <summary> /// 最初のonNextのみ通し、onCompletedを発行 /// </summary> private void ExcuteFirst() { Subject<int> subject = new Subject<int>(); subject .First() .Subscribe(x => { Debug.Log("First onNext : " + x); }, () => { Debug.Log("First onCompleted"); }); // 流れる subject.OnNext(1); // 流れない subject.OnNext(10); // 流れない subject.OnNext(100); }
結果
onCompletedを発行した時点での最後の値を発行
値を一度も流さずにonCompletedを呼ぶとエラーになってしまいます。
値を一度も流さずにonCompletedを呼びたい場合はLastOrDefaultを使用してください。
Last
/// <summary> /// onCompletedを発行した時点での最後の値を発行 /// </summary> private void ExcuteLast() { Subject<int> subject = new Subject<int>(); subject .Last() .Subscribe(x => { Debug.Log("Last onNext : " + x); }, () => { Debug.Log("Last onCompleted"); }); // 流れない subject.OnNext(1); // 流れない subject.OnNext(10); // 流れる subject.OnNext(100); subject.OnCompleted(); }
結果
OnNextが2回以上流れたら、onErrorを発行
値を一度も流さずにonCompletedを呼ぶとエラーになってしまいます。
値を一度も流さずにonCompletedを呼びたい場合はSingleOrDefaultを使用してください。
Single
/// <summary> /// OnNextが2回以上流れたら、onErrorを発行 /// </summary> private void ExcuteSingle() { Subject<int> subject = new Subject<int>(); subject .Single() .Subscribe(x => { Debug.Log("Single onNext : " + x); }, err => { Debug.Log("Single onError : " + err); }); subject.OnNext(1); // onErrorを発行 subject.OnNext(10); }
結果
指定した数だけ流す
Take
/// <summary> /// 指定した数だけ流す /// </summary> private void ExcuteTake() { Subject<int> subject = new Subject<int>(); int count = 3; subject .Take(count) .Subscribe(x => { Debug.Log("Take onNext : " + x); }); // 流れる subject.OnNext(1); // 流れる subject.OnNext(10); // 流れる subject.OnNext(100); // 流れない subject.OnNext(1000); // 流れない subject.OnNext(10000); }
結果
指定した条件を満たしている間は流し、一度でも満たしていないものが来たら以降は流さない
TakeWhile
/// <summary> /// 指定した条件を満たしている間は流し、一度でも満たしていないものが来たら以降は流さない /// </summary> private void ExcuteTakeWhile() { Subject<int> subject = new Subject<int>(); subject .TakeWhile(x => x > 10) .Subscribe(x => { Debug.Log("TakeWhile onNext : " + x); }); // 流れる subject.OnNext(100); // 流れる subject.OnNext(1000); // 流れない subject.OnNext(10); // 流れない subject.OnNext(10000); // 流れない subject.OnNext(100000); }
結果
指定したObservableのonNextが発行されるまで流す
TakeUntil
/// <summary> /// 指定したObservableのonNextが発行されるまで流す /// </summary> private void ExcuteTakeUntil() { Subject<int> subject = new Subject<int>(); Subject<int> otherSubject = new Subject<int>(); subject .TakeUntil(otherSubject) .Subscribe(x => { Debug.Log("TakeUntil onNext : " + x); }); // 流れる subject.OnNext(1); // 流れる subject.OnNext(10); otherSubject.OnNext(1); // 流れない subject.OnNext(100); }
結果
指定した数流さず、それ以降は流す
Skip
/// <summary> /// 指定した数流さず、それ以降は流す /// </summary> private void ExcuteSkip() { Subject<int> subject = new Subject<int>(); int count = 3; subject .Skip(count) .Subscribe(x => { Debug.Log("Skip onNext : " + x); }); // 流れない subject.OnNext(1); // 流れない subject.OnNext(10); // 流れない subject.OnNext(100); // 流れる subject.OnNext(1000); // 流れる subject.OnNext(10000); }
結果
指定した条件を満たしている間は流さず、一度でも満たしているものが来たら以降は流す
SkipWhile
/// <summary> /// 指定した条件を満たしている間は流さず、一度でも満たしているものが来たら以降は流す /// </summary> private void ExcuteSkipWhile() { Subject<int> subject = new Subject<int>(); subject .SkipWhile(x => x > 10) .Subscribe(x => { Debug.Log("SkipWhile : onNext : " + x); }); // 流れない subject.OnNext(100); // 流れない subject.OnNext(1000); // 流れる subject.OnNext(10); // 流れる subject.OnNext(10000); // 流れる subject.OnNext(100000); }
結果
指定したObservableのonNextが発行されるまで流さない
SkipUntil
/// <summary> /// 指定したObservableのonNextが発行されるまで流さない /// </summary> private void ExcuteSkipUntil() { Subject<int> subject = new Subject<int>(); Subject<int> otherSubject = new Subject<int>(); subject .SkipUntil(otherSubject) .Subscribe(x => { Debug.Log("SkipUntil onNext : " + x); }); // 流れない subject.OnNext(1); // 流れない subject.OnNext(10); otherSubject.OnNext(1); // 流れる subject.OnNext(100); }
結果
OnErrorかonCompletedのみ流し、onNextは流さない
IgnoreElements
/// <summary> /// OnErrorかonCompletedのみ流し、onNextは流さない /// </summary> private void ExcuteIgnoreElements() { Subject<int> subject = new Subject<int>(); subject .IgnoreElements() .Subscribe(x => { Debug.Log("IgnoreElements onNext : " + x); }, err => { Debug.Log("IgnoreElements onError : " + err); }, () => { Debug.Log("IgnoreElements onCompleted "); }); // 流れない subject.OnNext(1); // 流れる subject.OnError(new System.Exception("error")); // この例だと流れないが、流れる subject.OnCompleted(); }
結果
今回は以上となります。
ここまでご視聴ありがとうございました。