我需要一个字典扩展名,该扩展名可以从任意字典([String: Any]
)中删除所有匹配的键。
一个用例示例如下:
["test", "staging"]
[
"foo": [ "bar": "tralala" ]
"test": [ "foo": "bar", "staging": "hi"]
"aaa": [ "bbb": "cccc", "staging": "jjj"]
]
预期结果:
[
"foo": [ "bar": "tralala" ]
"aaa": [ "bbb": "cccc"]
]
答案 0 :(得分:0)
不建议将Any
用作字典值的类型。在这种情况下,最好将字典定义为[String : [String : String]]
。
如果您真的无法避免使用任何字典,让我们定义一下具有多个级嵌套字典的字典:
let dictionary = [
"foo" : [ "bar": "tralala" ],
"test": [ "foo": "bar", "staging": "hi"],
"aaa" : [ "bbb": "cccc", "staging": "jjj"],
"d" : [ "e": "f", "g": ["h": "i", "test": "j"]],
]
并声明我们要删除的密钥:
let badKeys = ["test", "staging"]
这是一个删除不需要的键的递归函数:
func remove(_ keys: [String], from dict: [String: Any]) -> [String: Any] {
var filtered = dict.filter { !keys.contains($0.key) }
for entry in filtered {
if let value = entry.value as? [String : String] {
filtered[entry.key] = remove(badKeys, from: value)
}
}
return filtered
}
您可以像这样使用它:
let result = remove(badKeys, from: dictionary)
哪种产量:
[“ aaa”:[“ bbb”:“ cccc”],“ foo”:[“ bar”:“ tralala”],“ d”:[“ e”:“ f”,“ g”:[ “ h”:“ i”]]]
(请注意,字典是无序集合,因此结果的顺序可能会有所不同)
答案 1 :(得分:-1)
目前还不清楚您尝试了什么 以及您遇到了什么困难,您确实应该包括此内容-不这样做将成为您遭到否决的原因。 < / p>
但是,让我们看看是否可以提供帮助。您声明字典的类型为[String:Any]
,并且没有给出任何嵌套限制,因此我们将使用以下测试数据:
let sampleDict : [String:Any] =
[
"foo": [ "bar": "tralala" ],
"test": [ "foo": "bar", "staging": "hi"],
"staging" : 3,
"one" : [ "two" : [ "three" : 3, "staging" : 4.2]],
"aaa": [ "bbb": "cccc", "staging": "jjj"]
]
如果我们的算法能够应付任何问题(著名的遗言……)。
使用预定义方法并避免循环的简单算法:
[String:Any]
字典的任何值,将此算法递归地应用于该值。在Swift中:
func removeMatchingKeys(_ dict : [String:Any], _ keysToRemove : [String]) -> [String:Any]
{
return dict
// filter keeping only those key/value pairs
// where the key isn't in keysToRemove
.filter { !keysToRemove.contains($0.key) }
// map the values in the filtered dictionary recursing
// if the value is itself a [String:Any] dictionary
.mapValues
{ if let nested = $0 as? [String:Any]
// value is dictionary, recurse
{ return removeMatchingKeys(nested, keysToRemove) }
else
// value isn't a dictionary, leave as is
{ return $0 }
}
}
使用以下按键进行测试:
let sampleKeys = ["test", "staging"]
声明:
print( removeMatchingKeys(sampleDict, sampleKeys) )
产生:
["foo": ["bar": "tralala"], "aaa": ["bbb": "cccc"], "one": ["two": ["three": 3.0]]]
以上算法对数据进行了两次传递,首先对其进行过滤,然后对其进行映射。如果是且仅当这是一个性能问题,则可以用一个简单的手写循环将两个预定义的函数filter
和map
替换为一个合并了操作的手写循环并且只传递一次数据。
注意:以上代码使用的是Xcode 10 / Swift 4.2,其他任何版本和YMMV(即语法和预定义函数可能很容易不同),但是该算法仍然适用。