如何编写一个通用的Swift扩展来深度合并两个字典? [英] How do I write a generic Swift extension to deep merge two dictionaries?

查看:1074
本文介绍了如何编写一个通用的Swift扩展来深度合并两个字典?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



这是我的:

 扩展词典{
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
}
}
返回结果


但不幸的是,编译。我得到错误


无法将类型'[Key:Value]'的值转换为期望参数类型[_:_]'在递归调用'deepMerged(with:)'时使用值。

我可以通过扩展范围:

 扩展词典其中键==字符串,值==任何{
...
}

这个适用于我目前特定的用例,但我不明白为什么更通用代码无法正常工作。

解决方案

请注意,错误出现在 result [key] ,而不是在函数调用本身:

  let merged:[Key:Value] = existing。 deepMerged(with:value)//正常工作
result [key] =合并//错误



<编译器知道:


  • result 是一个 [密钥:值]

  • :Value]


  • 是一个

  • 合并 [Key:Value]

  • result 有一个下标(key:Key) - >值? {get set} (即一个类型 Value?的可写下标,它接受 Key



不过 知道 [Key:Value] code>是一个,所以它不知道 merged 可以传递给结果。由于并且也是 [Key:Value] ,我们知道 [Key:Value] 必须是 Value ,但编译器不知道这一点。



解决方案是将 merged 转换为价值

 扩展词典{
public func deepMerged与其他:[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],
let merged = existing.deepMerged(with:value)as?值
{
结果[键] =合并
}其他{
结果[键] =值
}
}
返回结果
}
}


I'm trying to write a function to deep merge two dictionaries. By this I mean that when the values for a key in both dictionaries are being merged and those values are both dictionaries, they will be merged instead of one being replaced by the other.

Here's what I have:

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
    }
}

But unfortunately it doesn't compile. I get the error

Cannot convert value of type '[Key : Value]' to expected argument type [_ : _]' on the use of value in the recursive call to `deepMerged(with:).

I'm able to work around this by scoping the extension:

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

This works for my particular use case at this time, but I don't understand why the more generic code doesn't work.

解决方案

Note that the error is on the assignment to result[key], not on the function call itself:

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

The compiler knows that:

  • result is a [Key: Value]
  • other is a [Key: Value]
  • key is a Key
  • value is a Value
  • merged is a [Key:Value]
  • result has a subscript(key: Key) -> Value? { get set } (i.e. a writable subscript of type Value? which accepts a Key)

But it does not know that [Key:Value] is a Value, so it does not know that merged can be passed to the subscript of result. Since value is a Value and value is also [Key: Value], we know that [Key: Value] must be a Value, but the compiler does not know that.

A solution is to cast merged to a Value:

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],
                let merged = existing.deepMerged(with: value) as? Value
            {
                result[key] = merged
            } else {
                result[key] = value
            }
        }
        return result
    }
}

这篇关于如何编写一个通用的Swift扩展来深度合并两个字典?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆