我有一个变量,它是一个枚举值数组。这些值随时间而变化。
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内置了哪些内容可以更好地管理它?有没有办法总是从信号中获取先前值和当前值?
答案 0 :(得分:16)
这是一个方便的通用扩展,应该涵盖这些“我想要前一个和当前值”用例:
extension ObservableType {
func withPrevious(startWith first: E) -> Observable<(E, E)> {
return scan((first, first)) { ($0.1, $1) }.skip(1)
}
}
答案 1 :(得分:9)
你去了
docker run-it --privileged -v /dev/bus/usb:/dev/bus/usb -v (shared directory path):(path in container) debian:latest bash
它将返回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 }
:)
答案 2 :(得分:5)
正如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)
希望有所帮助
答案 3 :(得分: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)
答案 4 :(得分:1)
一行中的最佳解决方案:
Observable.zip(options, options.skip(1))
答案 5 :(得分:1)
.pairwise()
运算符完全可以完成您想要的操作,并且是执行此操作的最简单方法。该运算符将成对的连续发射分组在一起,并以两个值的数组形式发射它们。
请参阅: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提供了pairwise扩展运算符,类似于内置RxJS运算符
答案 6 :(得分:0)
另一种扩展方式
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)