假设我有一本相当复杂的字典,比如这个:
let dict: [String: Any] = [
"countries": [
"japan": [
"capital": [
"name": "tokyo",
"lat": "35.6895",
"lon": "139.6917"
],
"language": "japanese"
]
],
"airports": [
"germany": ["FRA", "MUC", "HAM", "TXL"]
]
]
我可以使用 if let ..
block 访问所有字段,在阅读时可选择转换为我可以使用的内容。
但是,我目前正在编写单元测试,我需要以多种方式有选择地破坏字典。
但我不知道如何优雅地从字典中删除键。
例如,我想在一个测试中删除键 "japan"
,在下一个测试中 "lat"
应该为 nil。
这是我当前用于删除 "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
}
一定有更优雅的方式吗?
理想情况下,我会编写一个测试助手,它采用 KVC 字符串并具有如下签名:
func dictWithoutKeyPath(_ path: String) -> [String: Any]
在 "lat"
的情况下,我会用 dictWithoutKeyPath("countries.japan.capital.lat")
来调用它。
最佳答案
使用下标时,如果下标是 get/set 且变量是可变的,则整个表达式都是可变的。但是,由于类型转换,表达式“失去”了可变性。 (不再是 l-value)。
解决这个问题的最短方法是创建一个获取/设置的下标并为您进行转换。
extension Dictionary {
subscript(jsonDict key: Key) -> [String:Any]? {
get {
return self[key] as? [String:Any]
}
set {
self[key] = newValue as? Value
}
}
}
现在您可以编写以下内容:
dict[jsonDict: "countries"]?[jsonDict: "japan"]?[jsonDict: "capital"]?["name"] = "berlin"
我们非常喜欢这个问题,所以我们决定制作一个(公开的)Swift Talk 剧集:mutating untyped dictionaries
关于ios - 从字典中删除嵌套键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40261857/