从字典中删除嵌套的键 [英] Remove nested key from dictionary

查看:178
本文介绍了从字典中删除嵌套的键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个相当复杂的字典,就像这样:

  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屋!

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