Sliding windows in RxSwift
出于RxJava的背景,我无法提出在RxSwift中实现滑动窗口的标准方法。 例如。 我有以下事件序列:
1 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, ... |
假设事件发射在一秒钟内发生两次。 我想要做的是将这个序列转换为一个缓冲区序列,每个缓冲区包含最后三秒钟的数据。 另外,每个缓冲区将每秒发出一次。 因此结果将如下所示:
1 | [1,2,3,4,5,6], [3,4,5,6,7,8], [5,6,7,8,9,10], ... |
我在RxJava中要做的是使用
1 | stream.buffer(3000, 1000, TimeUnit.MILLISECONDS) |
这正是我需要完成的结果:缓冲区序列,每个缓冲区每秒发出一次,并且包含最后三秒钟的数据。
我到处检查了RxSwift文档,但没有发现
我最初使用自定义运算符编写了解决方案。 从那以后,我就知道了如何使用标准运算符来完成。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | extension ObservableType { func buffer(timeSpan: RxTimeInterval, timeShift: RxTimeInterval, scheduler: SchedulerType) -> Observable<[E]> { let trigger = Observable<Int>.timer(timeSpan, period: timeShift, scheduler: scheduler) .takeUntil(self.takeLast(1)) let buffer = self .scan([Date: E]()) { previous, current in var next = previous let now = scheduler.now next[now] = current return next.filter { $0.key > now.addingTimeInterval(-timeSpan) } } return trigger.withLatestFrom(buffer) .map { $0.sorted(by: { $0.key <= $1.key }).map { $0.value } } } } |
我将以下原始解决方案留给后代使用:
解决方案是编写自己的运算符。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | extension ObservableType { func buffer(timeSpan: RxTimeInterval, timeShift: RxTimeInterval, scheduler: SchedulerType) -> Observable<[E]> { return Observable.create { observer in var buf: [Date: E] = [:] let lock = NSRecursiveLock() let elementDispoable = self.subscribe { event in lock.lock(); defer { lock.unlock() } switch event { case let .next(element): buf[Date()] = element case .completed: observer.onCompleted() case let .error(error): observer.onError(error) } } let spanDisposable = scheduler.schedulePeriodic((), startAfter: timeSpan, period: timeShift, action: { state in lock.lock(); defer { lock.unlock() } let now = Date() buf = buf.filter { $0.key > now.addingTimeInterval(-timeSpan) } observer.onNext(buf.sorted(by: { $0.key <= $1.key }).map { $0.value }) }) return Disposables.create([spanDisposable, elementDispoable]) } } } |