结合取消收集运算符?

Sen*_*ful 1 ios swift combine

我正在寻找一个与收集运算符相反的运算符:

  • 允许您从一个发射值映射到多个发射值,并将它们发射到流上。例如,如果我在流中有该元素,我想将其转换为发出then 、then 的[1,2,3]流。123
  • 不更改流的完成状态。诚然,该uncollect运算符不会与“ collectsincecollect等待流完成”完全相反。使用uncollect它应该只在流未完成时处理结果,而不是尝试完成/取消完成流。

例如,我想象这就是uncollect操作员的运作方式:

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) }
Run Code Online (Sandbox Code Playgroud)

我一直在寻找诸如explodesplat、 或 之类的名字uncollect,但没有成功。最接近的拥有一个有前途的名字的运算符是“ flatMapsince” Sequence.flatMap,它在非组合世界中是等效的。然而,CombineflatMap是将 Promise 链接在一起的方法

有没有办法取消收集元素,或将单个排放映射为任意数量的排放?


我能够让它与我的自定义JustSeveralPublisher一起使用,但这看起来很笨拙:

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()
  }
}
Run Code Online (Sandbox Code Playgroud)

Joa*_*son 7

您可以flatMap与新发布商一起使用

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

1
2
3
4
5
6