Наблюдаемые свойства плоского сопоставления в наблюдаемой коллекции в RxSwift

Используя RxSwift, скажем, у меня есть класс A, который содержит наблюдаемую целочисленную

class A: {
    let count: Observable<Int>
}

и наблюдаемый набор объектов A

let data: Observable<[A]>

Я хочу определить sum: Observable<Int>, который будет суммой всех count на всех объектах в data. Каждый раз, когда изменяется наблюдаемая коллекция data или изменяется какое-либо свойство count, sum также должен измениться.

Как этого добиться? Я пробовал несколько комбинаций flapMap и map, но нашел решение только тогда, когда sum обновляется только при обновлении data, игнорируя count изменения.


person Igor Kulman    schedule 25.08.2017    source источник


Ответы (1)


let sum = data.flatMap { Observable.from($0).flatMap { $0.count }.reduce(0, accumulator: +) }

'.reduce ()' излучает только после завершения, поэтому он должен быть внутри внешнего '.flatMap ()'

Обновление 1:

        let sumSubject: BehaviorSubject<Observable<Int>> = BehaviorSubject.create(Observable.empty())
        let sum = sumSubject.switchLatest()
        // every time it has to be a new 'data' observable!
        sumSubject.onNext(data.flatMap { Observable.from($0).flatMap { $0.count }.reduce(0, accumulator: +) })

Обновление 2:

    let counts: Observable<[Int]> = data.flatMap { Observable.combineLatest($0.map { $0.count }) }
    let sum: Observable<Int> = counts.map { $0.reduce(0) { $0 + $1 } }
person Maxim Volgin    schedule 25.08.2017
comment
Это просто 0 для меня. Версия до редактирования выдавала правильное значение первый раз, но не выдавала новое, когда count обновлялся. - person Igor Kulman; 25.08.2017
comment
Попробуйте добавить '.debug ()' после каждого оператора, чтобы выяснить, где завершается восходящий поток каждого оператора. По сути, '.reduce ()' генерирует только после завершения восходящего потока, тогда как '.scan ()' - для каждого восходящего элемента. Если ничего не помогает, попробуйте '.switchLatest ()' на 'BehaviourSubject ‹Observable‹ [A] ››', который вы будете кормить новым 'Observable.just ([A (), A (), ...]) ' - person Maxim Volgin; 25.08.2017
comment
Проблема со сканированием (в версии до редактирования) заключается в том, что он просто продолжает добавлять числа, когда что-то изменяется, не считая их снова. Например, когда счет меняется с 1 на 2, результат будет не 2, а 3 (1 + 2). - person Igor Kulman; 25.08.2017
comment
Ваше решение приводит к Observable<Int>, который генерирует счетчики по мере их изменения, нет хорошего способа сделать счет из этого. Думаю, целью было бы каким-то образом добраться до Observable<[Int]>. - person Igor Kulman; 25.08.2017
comment
Как "data.flatMap {Observable.combineLatest ($ 0.map {$ 0.count})}"? Хорошая точка зрения. - person Maxim Volgin; 25.08.2017