从字典中删除嵌套的键 [英] Remove nested key from dictionary
问题描述
let dict:[String:Any] = [
countries:[
japan:[
capital:[
name:tokyo,
lat:35.6895 ,
lon:139.6917
],
language:japanese
]
],
b $ bgermany:[FRA,MUC,HAM,TXL]
]
]
我可以使用访问所有字段,如果let ..
阻止可以转换为可以使用的东西,当阅读时。
但是,我正在编写单元测试,我需要以多种方式有选择地打破字典。
但我不知道如何从字典中优雅地删除密钥。
例如我想在一个测试中删除密钥japan
,下一个lat
应该为零。
这是我目前的删除lat
的实现:
如果var countries = dict [countries] as? [String:Any],
var japan = countries [japan] as? [String:Any],
var capital = japan [capital] as? [String:Any]
{
capital.removeValue(forKey:lat)
japan [capital] = capital
countries [japan] = japan
dictWithoutLat [countries] = countries
}
当然必须有更多优雅的方式?
理想情况下,我会写一个测试帮手,需要一个KVC字符串,并具有如下的签名:
func dictWithoutKeyPath(_ path:String) - > [String:Any]
在lat
case我会称之为 dictWithoutKeyPath(countries.japan.capital.lat)
。
当使用下标时,如果下标是get / set,变量是可变的,则整个表达式是可变的。然而,由于类型转换,表达式失去可变性。 (这不再是 l值)。
解决这个问题的最短的方法是创建一个下标,这个下标是get / set,并为您进行转换。
扩展字典{
subscript(jsonDict key:Key) - > [字符串:任何]? {
get {
return self [key] as? [String:Any]
}
set {
self [key] = newValue as?价值
}
}
}
现在你可以写以下:
dict [jsonDict:countries]?[jsonDict:japan]?[jsonDict:capital] ?[name] =berlin
我们很喜欢这个问题,关于它的(公开)Swift Talk插曲:突变无类型字典
Let's say I have a rather complex dictionary, like this one:
let dict: [String: Any] = [
"countries": [
"japan": [
"capital": [
"name": "tokyo",
"lat": "35.6895",
"lon": "139.6917"
],
"language": "japanese"
]
],
"airports": [
"germany": ["FRA", "MUC", "HAM", "TXL"]
]
]
I can access all fields with if let ..
blocks optionally casting to something that I can work with, when reading.
However, I am currently writing unit tests where I need to selectively break dictionaries in multiple ways.
But I don't know how to elegantly remove keys from the dictionary.
For example I want to remove the key "japan"
in one test, in the next "lat"
should be nil.
Here's my current implementation for removing "lat"
:
if var countries = dict["countries"] as? [String: Any],
var japan = countries["japan"] as? [String: Any],
var capital = japan["capital"] as? [String: Any]
{
capital.removeValue(forKey: "lat")
japan["capital"] = capital
countries["japan"] = japan
dictWithoutLat["countries"] = countries
}
Surely there must be a more elegant way?
Ideally I'd write a test helper that takes a KVC string and has a signature like:
func dictWithoutKeyPath(_ path: String) -> [String: Any]
In the "lat"
case I'd call it with dictWithoutKeyPath("countries.japan.capital.lat")
.
When working with a subscript, if the subscript is get/set and the variable is mutable, then the entire expression is mutable. However, due to the type cast the expression "loses" the mutability. (It's not an l-value anymore).
The shortest way to solve this is by creating a subscript that is get/set and does the conversion for you.
extension Dictionary {
subscript(jsonDict key: Key) -> [String:Any]? {
get {
return self[key] as? [String:Any]
}
set {
self[key] = newValue as? Value
}
}
}
Now you can write the following:
dict[jsonDict: "countries"]?[jsonDict: "japan"]?[jsonDict: "capital"]?["name"] = "berlin"
We liked this question so much that we decided to make a (public) Swift Talk episode about it: mutating untyped dictionaries
这篇关于从字典中删除嵌套的键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!