gre*_*sch 4 recursion closures dictionary swift
在给定的Dictionary中,我需要找到[String : Any]给定键的嵌套Dictionary()。
字典的一般结构(例如嵌套级别,值类型)是未知的,并且是动态给出的。[1]
在此子词典中,有一个需要获取的键“值”(不询问)的给定值。
这是一个例子:
let theDictionary: [String : Any] =
[ "rootKey" :
[ "child1Key" : "child1Value",
"child2Key" : "child2Value",
"child3Key" :
[ "child3SubChild1Key" : "child3SubChild1Value",
"child3SubChild2Key" :
[ "comment" : "child3SubChild2Comment",
"value" : "child3SubChild2Value" ]
],
"child4Key" :
[ "child4SubChild1Key" : "child4SubChild1Value",
"child4SubChild2Key" : "child4SubChild2Value",
"child4SubChild3Key" :
[ "child4SubChild3SubChild1Key" :
[ "value" : "child4SubChild3SubChild1Value",
"comment" : "child4SubChild3SubChild1Comment" ]
]
]
]
]
Run Code Online (Sandbox Code Playgroud)
通过蛮力和伪记忆,我设法一起破解了一个功能,该功能遍历整个Dictionary并获取给定键的值:
func dictionaryFind(_ needle: String, searchDictionary: Dictionary<String, Any>) -> String? {
var theNeedleDictionary = Dictionary<String, Any>()
func recurseDictionary(_ needle: String, theDictionary: Dictionary<String, Any>) -> Dictionary<String, Any> {
var returnValue = Dictionary<String, Any>()
for (key, value) in theDictionary {
if value is Dictionary<String, Any> {
if key == needle {
returnValue = value as! Dictionary<String, Any>
theNeedleDictionary = returnValue
break
} else {
returnValue = recurseDictionary(needle, theDictionary: value as! Dictionary<String, Any>)
}
}
}
return returnValue
}
// Result not used
_ = recurseDictionary(needle, theDictionary: searchDictionary)
if let value = theNeedleDictionary["value"] as? String {
return value
}
return nil
}
Run Code Online (Sandbox Code Playgroud)
到目前为止,该方法有效。(为您的游乐场测试带来乐趣:
let theResult1 = dictionaryFind("child3SubChild2Key", searchDictionary: theDictionary)
print("And the result for child3SubChild2Key is: \(String(describing: theResult1!))")
let theResult2 = dictionaryFind("child4SubChild3SubChild1Key", searchDictionary: theDictionary)
print("And the result for child4SubChild3SubChild1Key is: \(String(describing: theResult2!))")
let theResult3 = dictionaryFind("child4Key", searchDictionary: theDictionary)
print("And the result for child4Key is: \(String(describing: theResult3))")
Run Code Online (Sandbox Code Playgroud)
)。
我的问题在这里:
什么是更干净,简洁,“快捷”的方法来遍历字典,尤其是在找到所需的密钥后完全脱离常规?
甚至可以使用Dictionary扩展实现解决方案吗?
谢谢大家!
更为紧凑的递归解决方案可能是:
func search(key:String, in dict:[String:Any], completion:((Any) -> ())) {
if let foundValue = dict[key] {
completion(foundValue)
} else {
dict.values.enumerated().forEach {
if let innerDict = $0.element as? [String:Any] {
search(key: key, in: innerDict, completion: completion)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
用法是:
search(key: "child3SubChild2Key", in: theDictionary, completion: { print($0) })
Run Code Online (Sandbox Code Playgroud)
这使:
["comment": "child3SubChild2Comment", "value": "child3SubChild2Subchild1Value"]
Run Code Online (Sandbox Code Playgroud)
或者,如果您不想使用闭包,则可以使用以下代码:
extension Dictionary {
func search(key:String, in dict:[String:Any] = [:]) -> Any? {
guard var currDict = self as? [String : Any] else { return nil }
currDict = !dict.isEmpty ? dict : currDict
if let foundValue = currDict[key] {
return foundValue
} else {
for val in currDict.values {
if let innerDict = val as? [String:Any], let result = search(key: key, in: innerDict) {
return result
}
}
return nil
}
}
}
Run Code Online (Sandbox Code Playgroud)
用法是:
let result = theDictionary.search(key: "child4SubChild3SubChild1Key")
print(result) // ["comment": "child4SubChild3SubChild1Comment", "value": "child4SubChild3SubChild1Value"]
Run Code Online (Sandbox Code Playgroud)