Help us understand the problem. What is going on with this article?

RxSwiftで、2回に1回イベントを流すObservableを作ってみた

More than 1 year has passed since last update.

2番煎じかもしれませんが、ざっと探したら見つからなかったので。
他にあれば教えて下さい(笑い

実装方針

  • scanを使って、Bool値をtrue -> false -> true -> falseのように都度切り替えて流す
  • そのBool値をつかって、filterする
let intSubject = PublishSubject<Int>()
let subject =
    intSubject
        .scan((true, 0)) { (output, update) -> (Bool, Int) in
            //Bool値を反転して返してあげると、ストリームの度に値が変わることになる
            //初期値はtrueを反転するのでfalseから始まる。結果として奇数回を飛ばすことになる
            return (!output.0, update)
        }
        .compactMap { (flag, value) -> Int? in
            flag ? value : nil
        }
subject.bind { print($0) }

intSubject.onNext(1)
intSubject.onNext(2)
intSubject.onNext(3)
intSubject.onNext(4)
intSubject.onNext(5)
intSubject.onNext(6)
//結果
2
4
6

compactMap使ってますので、流す型がInt? だとおかしくなりますね。素直に filterとmapで書いたほうが良さそうです。あとはscanの初期値として渡している 0 も型を特定する以上の役割がないので要らないかなぁ

汎用化してみました

extension をつかって、Observableの関数化してみます。

extension Observable {
    //isEvenは偶数回だけイベントを流すか、奇数回だけにするかを決定するフラグ
    func onceInTwice(isEven: Bool) -> Observable<Element> {
        let initial: (Bool,[Element]) = (isEven, [])
        return
            scan(initial) { (output, update) -> (Bool, [Element]) in
                return (!output.0, [update])
            }
            .filter { (flag, _) in return flag }
            .map { (_, value)  in return value.first! }
    }
}

let input = PublishSubject<String?>()
let onceInTwice = input.onceInTwice(isEven: false)

onceInTwice.bind { print($0) }

input.onNext("1回目")
input.onNext("2回目")
input.onNext(nil)
input.onNext("4回目")
input.onNext("5回目")
input.onNext("6回目")

//結果
Optional("1回目")
nil
Optional("5回目")

期待どおりに動いてくれてそうです〜。

shintax
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away