簡體   English   中英

結合 uncollect 運算符?

[英]Combine uncollect operator?

我正在尋找與收集運算符相反的運算符:

  • 允許您將 map 從一個發射值轉換為多個發射值,在 stream 上發射它們。 例如,如果我在 stream 中有元素[1,2,3] ,我想將其轉換為 stream 發出1然后2 ,然后3
  • 不會更改流的完成 state。 誠然,這個uncollect運算符不會與collect完全相反,因為collect一直等到 stream 完成。 使用uncollect它應該只在 stream 未完成時處理結果,而不是嘗試完成/取消 stream。

例如,我想這就是uncollect運算符 function 的方式:

func fibonacci(_ number: Int) -> AnyPublisher<Int, Never> {
  Future { ... }.eraseToAnyPublisher()
}

let serverEventStream: AnyPublisher<[Int], Never> = ...

serverEventStream              // AnyPublisher<[Int], Never>  // Ex. 2 values: `[12, 24]`, `[1, 10, 50]`
  .uncollect { $0 }            // AnyPublisher<Int, Never>    // Ex. 5 values: `12`, `24`, `1`, `10`, `50`
  .flatMap { fibonacci($0) }   // AnyPublisher<Int, Never>    // Ex. 5 values: `144`, `46368`, `1`, `55`, `12586269025`
  .sink { print($0) }

我一直在尋找諸如explodesplatuncollect之類的名稱,但無濟於事。 最接近的運算符是flatMap ,因為Sequence.flatMap在非組合世界中是等價的。 然而, Combine 的flatMap是將 Promise 鏈接在一起的方式

有沒有辦法取消收集元素,或者 map 將單個發射變成任意數量的發射?


我能夠讓它與我的自定義JustSeveral Publisher一起使用,但這似乎很笨重:

class Tests: XCTestCase {
  func testUncollect() {
    func fibonacci(_ number: Int) -> AnyPublisher<Int, Never> {
      switch number {
      case 1: return Just(1).eraseToAnyPublisher()
      case 10: return Just(55).eraseToAnyPublisher()
      case 12: return Just(144).eraseToAnyPublisher()
      case 24: return Just(46368).eraseToAnyPublisher()
      case 50: return Just(12586269025).eraseToAnyPublisher()
      default: fatalError("Should actually build this function.")
      }
    }

    let serverEventStream: AnyPublisher<[Int], Never> = JustSeveral([[12, 24], [1, 10, 50]]).eraseToAnyPublisher()

    serverEventStream              // AnyPublisher<[Int], Never>  // Ex. 2 values: `[12, 24]`, `[1, 10, 50]`
      .uncollect { $0 }            // AnyPublisher<Int, Never>    // Ex. 5 values: `12`, `24`, `1`, `10`, `50`
      .flatMap { fibonacci($0) }   // AnyPublisher<Int, Never>    // Ex. 5 values: `144`, `46368`, `1`, `55`, `12586269025`
      .sink { print($0) }
  }
}

extension Publisher {
  func uncollect<T>(_ transform: @escaping (Output) -> [T]) -> AnyPublisher<T, Failure> {
    self
      .flatMap { output -> AnyPublisher<T, Failure> in
        JustSeveral(transform(output))
          .setFailureType(to: Failure.self)
          .eraseToAnyPublisher()
      }
      .eraseToAnyPublisher()
  }
}

您可以將flatMap與新的發布者一起使用

[1,2,3,4,5,6].publisher
    .collect()
    .flatMap { $0.publisher }
    .sink { print($0) }

1
2
3
4
5
6

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM