列挙値の配列である変数があります。これらの値は時間とともに変化します。
enum Option {
case One
case Two
case Three
}
let options = Variable<[Option]>([ .One, .Two, .Three ])
次に、この変数の変化を観察します。問題は、最新の値と以前の値の違いを知る必要があることです。私は現在これをやっています:
let previousOptions: [Option] = [ .One, .Two, .Three ]
...
options
.asObservable()
.subscribeNext { [unowned self] opts in
// Do some work diff'ing previousOptions and opt
// ....
self.previousOptions = opts
}
これをよりよく管理するRxSwiftに組み込まれているものはありますか?常に信号から以前の値と現在の値を取得する方法はありますか?
そこに行きます
_options.asObservable()
.scan( [ [],[] ] ) { seed, newValue in
return [ seed[1], newValue ]
}
// optional, working with Tuple of array is better than array of array
.map { array in (array[0], array[1]) }
//optional, in case you dont want empty array
.skipWhile { $0.count == 0 && $1.count == 0 }
_
Observable<([Options], [Options])>
を返します:)
以下は、これらをカバーする便利な汎用拡張です"私は以前の値と現在の値が必要です"使用例:
extension ObservableType {
func withPrevious(startWith first: E) -> Observable<(E, E)> {
return scan((first, first)) { ($0.1, $1) }.skip(1)
}
}
Pham Hoanが言ったように、scan(_)
はその仕事に適したツールです。 Marin Todorovさんは、まさにこれを行うことについて good post を書きました。
マリンの投稿に基づいて、これが私が思いついたものです:
options
.asObservable()
.scan([]) {
(previous, current) in
return Array(previous + [current]).suffix(2)
}
.subscribeNext {
(lastTwoOptions) in
let previousOptions = lastTwoOptions.first
let currentOptions = lastTwoOptions.last
// Do your thing. Remember to check for nil the first time around!
}
.addDisposableTo(self.disposeBag)
それが役に立てば幸い
拡張としての別の方法
extension ObservableType {
func withPrevious() -> Observable<(E?, E)> {
return scan([], accumulator: { (previous, current) in
Array(previous + [current]).suffix(2)
})
.map({ (arr) -> (previous: E?, current: E) in
(arr.count > 1 ? arr.first : nil, arr.last!)
})
}
}
使用法:
someValue
.withPrevious()
.subscribe(onNext: { (previous, current) in
if let previous = previous { // previous is optional
print("previous: \(previous)")
}
print("current: \(current)")
})
.disposed(by: disposeBag)
1行での最適なソリューション:
Observable.Zip(options, options.skip(1))
私はこのようなものを提案します(将来の訪問者向け):
options.asObservable()
.map { (old: [], new: $0) } // change type from array to Tuple
.scan((old: [], new: [])) { previous, current in
// seed with an empty Tuple & return both information
return (old: previous.new, new: current.new)
}
.subscribe(onNext: { option in
let oldArray = option.old // old
let newArray = option.new // new
}
.addDisposableTo(disposeBag)
.pairwise()
演算子は、まさに望みどおりのことを行い、それを行う最も簡単な方法です。この演算子は、連続する放出のペアをグループ化し、2つの値の配列として放出します。
参照: http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-pairwise
または https://rxjs-dev.firebaseapp.com/api/operators/pairwise
更新:@courteouselkが彼のコメントで指摘したように、私はこれがRxSwiftの質問であることに気付かず、私の回答はRxJSソリューションを参照しました(おっと!)。
RxSwiftには組み込みのpairwise
演算子がないことがわかりますが、 RxSwiftExt は ペアワイズ 組み込みのRxJS演算子に似た拡張演算子。