合并取消选择运算符



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

  • 允许您从一个发射值映射到多个发射值,在流上发射它们。例如,如果流中有元素[1,2,3],我想将其转换为一个先发出1,然后发出2,再发出3的流
  • 不会更改流的完成状态。诚然,该uncollect运算符不会与collect完全相反,因为collect等待直到流结束。对于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) }

我一直在寻找像explodesplatuncollect这样的名字,但都无济于事。共享一个有前途的名称的最接近的运算符是flatMap,因为Sequence.flatMap在非Combine世界中是等价的。然而,Combine的flatMap是将承诺链接在一起的方式。

有没有一种方法可以取消元素的选择,或者将单个排放映射为任意数量的排放?


我能够让它与我的自定义JustSeveral发布服务器一起工作,但这似乎很笨拙:

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

最新更新