LoginSignup
18
11

More than 5 years have passed since last update.

【Swift】RxSwiftのPlaygroundを読む⑤

Last updated at Posted at 2016-07-22

RxSwiftのPlaygroundを読んでみるシリーズ今回は
条件如何で流したり、あるいは流さなかったりする操作についてです。
(Filtering_and_Conditional_Operators)

Filtering and Conditional Operators

様々に条件を設定し、条件に適えばそのまま値を流し、条件に合わなければ値を流しません。
堰のような役割をはたします。

filter

流れてくる値に基づき条件を記述し、条件に合うものだけを流す。

let disposeBag = DisposeBag()

Observable.of(
    "🍑", "🍐", "🍎",
    "🍇", "🍑", "🍐",
    "🍎", "🍇", "🍑"
    )
    .filter {
        $0 == "🍑" // 🍑だけを流す
    }
    .subscribe { print($0) }
    .addDisposableTo(disposeBag)

結果

Next(🍑)
Next(🍑)
Next(🍑)
Completed

distinctUntilChanged

流れてくる値が、前回と違う値だったときのみ流す。

let disposeBag = DisposeBag()

Observable.of(
    "🍑", "🍑", "🍑",
    "🍎", "🍎", "🍎",
    "🍐", "🍐", "🍐"
    )
    .distinctUntilChanged()
    .subscribe { print($0) }
    .addDisposableTo(disposeBag)

結果

Next(🍑)
Next(🍎)
Next(🍐)
Completed

elementAt

指定したインデックスの値のみ流す。

let disposeBag = DisposeBag()

Observable.of("🍑", "🍊", "🍇","🍎", "🍏", "🍉")
    .elementAt(4)
    .subscribe { print($0) }
    .addDisposableTo(disposeBag)

結果

Next(🍏)
Completed

single

流れてくる最初の値のみを流す。
あるいは、指定した条件に適う最初の値のみ流す。

条件を指定しない場合に2つ以上の値が流れてきたときや、
条件を指定した場合に、合うものが複数あったとき・合うものがなかったときはerrorが流れる。

条件なし&流れる値が一つ

no_condition_and_just
let disposeBag = DisposeBag()

Observable.just("🍑")
    .single()
    .subscribe { print($0) }
    .addDisposableTo(disposeBag)
結果
Next(🍑)
Completed

条件なし&流れる値が複数

no_condition_and_of
let disposeBag = DisposeBag()

Observable.of("🍑", "🍊", "🍇","🍎", "🍏", "🍉")
    .single()
    .subscribe { print($0) }
    .addDisposableTo(disposeBag)
結果
Next(🍑)
Error(Sequence contains more than one element.)

条件あり&合うものが1つ

condition_and_single
let disposeBag = DisposeBag()

Observable.of("🍊", "🍇","🍎", "🍑", "🍏", "🍉")
    .single { $0 == "🍑" }
    .subscribe { print($0) }
    .addDisposableTo(disposeBag)
結果
Next(🍑)
Completed

条件あり&合うものが複数

condition_and_multiple
let disposeBag = DisposeBag()

Observable.of("🍊", "🍑","🍎", "🍑", "🍏", "🍉")
    .single { $0 == "🍑" }
    .subscribe { print($0) }
    .addDisposableTo(disposeBag)
結果
Next(🍑)
Error(Sequence contains more than one element.)

条件あり&合うものがない

condition_and_nothing
let disposeBag = DisposeBag()

Observable.of("🍊", "🍇","🍎", "🍐", "🍏", "🍉")
    .single { $0 == "🍑" }
    .subscribe { print($0) }
    .addDisposableTo(disposeBag)
結果
Error(Sequence doesn't contain any elements.)

take

流れてきた順に指定した数の値を流す。

let disposeBag = DisposeBag()

Observable.of("🍊", "🍇","🍎", "🍑", "🍏", "🍉")
    .take(3)
    .subscribe { print($0) }
    .addDisposableTo(disposeBag)

結果

Next(🍊)
Next(🍇)
Next(🍎)
Completed

takeLast

後ろから数えて指定した数の値を流す。

let disposeBag = DisposeBag()

Observable.of("🍊", "🍇","🍎", "🍑", "🍏", "🍉")
    .takeLast(3)
    .subscribe { print($0) }
    .addDisposableTo(disposeBag)

結果

Next(🍑)
Next(🍏)
Next(🍉)
Completed

takeWhile

条件を満たさなくなるまでは値を流し、それ以降は(条件に合っていても)値を流さない。

let disposeBag = DisposeBag()

Observable.of("🍑", "🍑","🍑", "🍏", "🍑", "🍑")
    .takeWhile { $0 == "🍑" }
    .subscribe { print($0) }
    .addDisposableTo(disposeBag)

結果

Next(🍑)
Next(🍑)
Next(🍑)
Completed

takeUntil

参照する川を指定し、
その川に値が流れるまでは値を流し、
一度参照する川に値が流れると流さなくなる。

let disposeBag = DisposeBag()

let main川      = PublishSubject<String>()
let reference川 = PublishSubject<String>()

main川.takeUntil(reference川)
    .subscribe { print($0) }
    .addDisposableTo(disposeBag)

main川.onNext("🍑0")
main川.onNext("🍑1")

reference川.onNext("🍏")

main川.onNext("🍑2")

結果

Next(🍑0)
Next(🍑1)
Completed

skip

流れてきた順に指定した数の値をスキップし、それ以降の値を流す。
takeと対照の関係。

let disposeBag = DisposeBag()

Observable.of("🍊", "🍇","🍎", "🍑", "🍏", "🍉")
    .skip(3)
    .subscribe { print($0) }
    .addDisposableTo(disposeBag)

結果

Next(🍑)
Next(🍏)
Next(🍉)
Completed

skipWhile

条件を満たす間は値をスキップし、それ以降は(条件に合っていても)値を流す。
takeWhileと対照の関係。

let disposeBag = DisposeBag()

Observable.of("🍑", "🍑","🍑", "🍏", "🍑", "🍑")
    .skipWhile { $0 == "🍑" }
    .subscribe { print($0) }
    .addDisposableTo(disposeBag)

結果

Next(🍏)
Next(🍑)
Next(🍑)
Completed

skipWhileWithIndex

skipWhileの条件の引数として、インデックスも受け取ることができる。

let disposeBag = DisposeBag()

Observable.of("🍑", "🍑","🍑", "🍏", "🍑", "🍑")
    .skipWhileWithIndex { element, index in
        index < 4
    }
    .subscribe { print($0) }
    .addDisposableTo(disposeBag)

結果

Next(🍑)
Next(🍑)
Completed

skipUntil

参照する川を指定し、
その川に値が流れるまでは値をスキップし、
一度参照する川に値が流れると値を流すようになる。
takeUntilと対照の関係。

let disposeBag = DisposeBag()

let main川      = PublishSubject<String>()
let reference川 = PublishSubject<String>()

main川.skipUntil(reference川)
    .subscribe { print($0) }
    .addDisposableTo(disposeBag)

main川.onNext("🍑0")
main川.onNext("🍑1")

reference川.onNext("🍏")

main川.onNext("🍑2")

結果

Next(🍑2)

おわりに

この辺をうまく組み合わせることができれば、
変幻自在な川を作れそうです。

次回は流れる値を集める操作についてです。

参考

18
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
11