如何编写通用的Swift扩展来深度合并两个字典?

时间:2017-07-20 16:31:36

标签: swift dictionary generics recursion

我试图编写一个函数来深度合并两个词典。我的意思是,当两个字典中的键的值被合并并且这些值都是字典时,它们将被合并而不是被另一个替换。

以下是我所拥有的:

extension Dictionary {
    public func deepMerged(with other: [Key: Value]) -> [Key: Value] {
        var result: [Key: Value] = self
        for (key, value) in other {
            if let value = value as? [Key: Value], let existing = result[key] as? [Key: Value] {
                result[key] = existing.deepMerged(with: value)
            } else {
                result[key] = value
            }
        }
        return result
    }
}

但不幸的是它没有编译。我收到了错误

  

无法转换类型的值' [Key:Value]'预期参数类型[_:_]'关于在`deepMerged(with :)中的递归调用中使用值。

我能够通过确定扩展名来解决这个问题:

extension Dictionary where Key == String, Value == Any {
    ...
}

这适用于我此时的特定用例,但我不明白为什么更通用的代码无效。

1 个答案:

答案 0 :(得分:3)

请注意,错误发生在result[key]的分配上,而不是函数调用本身:

let merged: [Key:Value] = existing.deepMerged(with: value)  //works fine
result[key] = merged                                        //error

编译器知道:

  • result[Key: Value]
  • other[Key: Value]
  • keyKey
  • valueValue
  • merged[Key:Value]
  • resultsubscript(key: Key) -> Value? { get set }(即Value?类型的可写下标,可接受Key

知道[Key:Value]Value,因此它不知道merged可以传递给{{1}的下标}}。由于resultvalueValue也是value,我们知道[Key: Value]必须是[Key: Value],但编译器不知道这一点。

解决方案是将Value投射到merged

Value