You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Combine中MergeMany+collect后erase报错及多数组发布者合并问题

问题:合并多个返回数组的Deferred Publisher并处理类型报错

我有两个返回Int数组的Deferred Publisher(底层为Future),希望它们并行运行后合并为一个Int数组(如p1返回的[1,2,3]与p2返回的[4,5,6]合并为[1,2,3,4,5,6]或[4,5,6,1,2,3])。尝试以下代码:

let p1: AnyPublisher<[Int], Never>
let p2: AnyPublisher<[Int], Never>
let combined: AnyPublisher<[Int], Never> = Publishers.MergeMany([p1, p2])
            .collect()
            .eraseToAnyPublisher()

出现错误:Type of expression is ambiguous without a type annotation,collect后的类型为Publishers.Collect<Publishers.MergeMany<AnyPublisher<[Int], Never>>>,但无法擦除为目标类型。尝试assign方式也报错:Cannot convert value of type 'AnyPublisher<[Reminder], Never>' to expected argument type 'Published<[AnyPublisher<[Reminder], Never>.Output]>.Publisher'。后续用Zip3实现了需求,但该方案无法适配任意数量的发布者且存在额外存储开销,希望了解原方法报错原因及更通用的解决方案。

报错原因分析

核心问题是类型不匹配:

  • Publishers.MergeMany([p1, p2])的输出是单个的[Int]元素(每个发布者完成时发送一次自己的数组)
  • .collect()会把所有发送的[Int]收集成一个[[Int]](数组的数组),而你期望的最终类型是[Int],直接擦除会因类型不一致引发歧义报错。

通用解决方案

要实现任意数量发布者并行执行后合并为单个Int数组,只需在collect()之后添加一个扁平化步骤,把[[Int]]转成[Int]即可。有两种常见方式:

方式1:使用reduce拼接数组

let p1: AnyPublisher<[Int], Never>
let p2: AnyPublisher<[Int], Never>
let combined: AnyPublisher<[Int], Never> = Publishers.MergeMany([p1, p2])
    .collect()
    .map { $0.reduce([], +) } // 将数组的数组拼接为单个数组
    .eraseToAnyPublisher()

方式2:使用joined()转成序列再转数组

let p1: AnyPublisher<[Int], Never>
let p2: AnyPublisher<[Int], Never>
let combined: AnyPublisher<[Int], Never> = Publishers.MergeMany([p1, p2])
    .collect()
    .map { Array($0.joined()) } // 扁平化序列并转为数组
    .eraseToAnyPublisher()

这两种方式都支持任意数量的输入发布者,且并行执行(MergeMany本身就是并行订阅所有子发布者),最终输出合并后的单个Int数组,顺序取决于各发布者的完成顺序(符合你对合并顺序的要求)。

内容的提问来源于stack exchange,提问作者CalebK

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 16:20:07