Как уменьшить массив Int Publishers на Combine? - PullRequest
0 голосов
/ 11 июля 2020

У меня есть массив Int plublishers, изменяемый через сеть, и я хотел бы присвоить его сумму переменной. Пока что я подошел к следующему:

cancellable = Publishers.MergeMany(items.map { $0.$count } ).sink { value in
           print(value) 
        }

Он печатает все значения, но на самом деле я хочу свести их все к одному значению, а затем назначить где-то еще. Но когда я пытаюсь уменьшить, что-то вроде:

   cancellable = Publishers.MergeMany(items.map { $0.$count } )
            .reduce(0){ counter, value in
                counter + value
            }.sink { value in
                print (value)
            }

, это больше не работает, значение никогда не печатается. Что я делаю не так? Спасибо

Изменить:

Кажется, это работает, но выглядит не очень эффективно

cancellable = Publishers.MergeMany(items.map { $0.$count })
      .sink { _ in
          let value = self.items.map { $0.count}.reduce(0) { counter, newValue in
              counter + newValue
          }
          print(value)
      }

Ответы [ 2 ]

0 голосов
/ 11 июля 2020

Ваше последнее изменение, в котором вы суммируете все значения в конце, на самом деле является наиболее простым подходом, который должен работать в большинстве типичных случаев. новую ценность любого издателя, вы суммируете ценности всех издателей - операция времени O (N).

Итак, чисто интеллектуальное упражнение , чтобы повысить эффективность, единственный способ сделать это за время O (1) - обновить некоторую накопленную сумму, добавив текущее значение и вычтя предыдущее значение того же издателя .

let initialSum = items.reduce(0, { $0 + $1.count })

// publishers of tuples of: (current, previous)
let publishers = items.map { $0.$count.scan(($0.count, 0), { ($1, $0.0) }) }

let cancellable = Publishers.MergeMany(publishers)
                      // add current, subtract previous
                      .scan(initialSum, { $0 + $1.0 - $1.1 } )
                      // the first run will produce duplicates of initial sum
                      .removeDuplicates()
                      .sink{ print($0) }
0 голосов
/ 11 июля 2020

Оператор reduce сводит все значения в аккумулятор. Он генерирует аккумулятор один раз в качестве своего единственного вывода, что происходит только после завершения восходящего издателя.

Я подозреваю, что вы ищете оператор scan. Он похож на reduce, но выдает аккумулятор при каждом событии.

...