ios - 从字典中删除嵌套键

标签 ios swift dictionary collections nsdictionary

假设我有一本相当复杂的字典,比如这个:

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/

相关文章:

iphone - 使用 segue 将 NSMutableArray 字典数据传递到另一个 View

ios - removeFromSuperview() 不起作用

dictionary - Ansible:更改嵌套变量的默认值

ios - UITableView 通过内容偏移获取中间位置

python - 在字典中执行幂运算

arrays - 以列表为值的 Bash 关联数组

ios - 使用来自 URL 的 JSON 数组并返回与 Swift 3 中的值匹配的行

iphone - 自动选择第一个 UITableView 文本框

ios - 如何在 Swift 中将触摸事件发送到 nextResponder

ios - nextTriggerDate() 不返回 'expected' 值,是否有其他方法来获取重复本地通知的下一个触发日期?