Kotlin 协程压缩三个流程

Fra*_*cis 5 kotlin kotlin-coroutines kotlin-coroutines-flow

zip功能可以压缩两个Flows。有什么东西可以将三个(或更多)压缩Flows在一起吗?

如果没有,你能帮我实现它的扩展功能吗?就像是:

flow.zip(flow2, flow3) { a, b, c -> 

}
Run Code Online (Sandbox Code Playgroud)

Ten*_*r04 2

我没有测试过这个,但你可以尝试一下。有很多底层代码zip,因此为了利用它,我将前两个流压缩成一个对流,然后将对流压缩到第三个流。但是传递给该函数的 lambda 得到的前两个已经分开,因此它不必知道中间的 Pair 步骤。

fun <T1, T2, T3, R> zip(
    first: Flow<T1>,
    second: Flow<T2>,
    third: Flow<T3>,
    transform: suspend (T1, T2, T3) -> R
): Flow<R> =
    first.zip(second) { a, b -> a to b }
        .zip(third) { (a, b), c ->
            transform(a, b, c)
        }
Run Code Online (Sandbox Code Playgroud)

用法如下:

zip(flow1, flow2, flow3) { a, b, c ->
    Triple(a, b, c)
}
Run Code Online (Sandbox Code Playgroud)

这是针对任意数量的流的未经测试的版本,但它们必须是相同的类型:

fun <T, R> zip(
    vararg flows: Flow<T>,
    transform: suspend (List<T>) -> R
): Flow<R> = when(flows.size) {
    0 -> error("No flows")
    1 -> flows[0].map{ transform(listOf(it)) }
    2 -> flows[0].zip(flows[1]) { a, b -> transform(listOf(a, b)) }
    else -> {
        var accFlow: Flow<List<T>> = flows[0].zip(flows[1]) { a, b -> listOf(a, b) }
        for (i in 2 until flows.size) {
            accFlow = accFlow.zip(flows[i]) { list, it ->
                list + it
            }
        }
        accFlow.map(transform)
    }
}
Run Code Online (Sandbox Code Playgroud)