如何编写一个通用的Swift扩展来深度合并两个字典? [英] How do I write a generic Swift extension to deep merge two dictionaries?
问题描述
我试图编写一个函数来深度合并两个字典。我的意思是,当两个字典中的键的值被合并并且这些值都是字典时,它们将被合并而不是被另一个替换。
这是我的:
扩展词典{
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 aKey
value
is aValue
merged
is a[Key:Value]
result
has asubscript(key: Key) -> Value? { get set }
(i.e. a writable subscript of typeValue?
which accepts aKey
)
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屋!