您如何利用 Swift 功能来重构此递归函数?
How can you leverage Swift features to refactor this recursive function?
我一直在研究递归函数,以从表示为 NSDictionary 的 JSON 数据中提取字符串值。该函数允许您这样做:
if let value = extractFromNestedDictionary(["fee" : ["fi" : ["fo" : "fum"]]], withKeys: ["fee", "fi", "fo"]) {
println("\(value) is the value after traversing fee-fi-fo");
}
函数实现如下所示:
// Recursively retrieves the nested dictionaries for each key in `keys`,
// until the value for the last key is retrieved, which is returned as a String?
func extractFromNestedDictionary(dictionary: NSDictionary, withKeys keys: [String]) -> String? {
if keys.isEmpty { return nil }
let head = keys[0]
if let result: AnyObject = dictionary[head] {
if keys.count == 1 {
return result as? String
} else {
let tail: [String] = Array(keys[1..<keys.count])
if let result = result as? NSDictionary {
return extractFromNestedDictionary(result, withKeys: tail)
} else {
return nil
}
}
} else {
return nil
}
}
在 Swift 1.2/2.x 中是否有一些与可选绑定相关的语法特征可以:
- 让这个功能更简洁
- 少用
if
嵌套
我本来不想在没有你先尝试的情况下就成功的,但我还是做了,因为我喜欢 Swift 并且很开心:
func extractFromNestedDictionary(dictionary: [NSObject : AnyObject], var withKeys keys: [String]) -> String? {
if let head = keys.first, result = dictionary[head] {
if keys.count == 1 {
return result as? String
} else if let result = result as? [NSObject : AnyObject] {
keys.removeAtIndex(0)
return extractFromNestedDictionary(result, withKeys: keys)
}
}
return nil
}
extractFromNestedDictionary(["A" : ["B" : ["C" : "D"]]], withKeys: ["A", "B", "C"])
一些注意事项:
- 尽量避免使用
NSDictionary
并使用 [NSObject : AnyObject]
代替,它无论如何都可以桥接到 NSDictionary 并且更 Swifty
- 问问题的时候,试着举一个比你在那里做的更好的例子,从你的例子中我无法知道你到底想做什么。
这是我想出的最好的...
func extractFromNestedDictionary(dictionary: [NSObject : AnyObject], withKeys keys: [String]) -> String? {
if let head = keys.first,
result = dictionary[head] as? String
where keys.count == 1 {
return result
} else if let head = keys.first,
result = dictionary[head] as? [NSObject : AnyObject] {
return extractFromNestedDictionary(result, withKeys: Array(keys[1..<keys.count]))
}
return nil
}
您可以在 keys
数组上使用 reduce
而不是递归
遍历字典:
func extractFromNestedDictionary(dictionary: NSDictionary, withKeys keys: [String]) -> String? {
return reduce(keys, dictionary as AnyObject?) {
([=10=] as? NSDictionary)?[]
} as? String
}
在闭包内部,[=13=]
是当前级别的(可选)对象,</code>
当前密钥。闭包return是下一层的对象
如果 <code>[=13=]
是一个字典 and 有当前键的值,
nil
否则。 reduce()
的 return 值是
最后一层的对象或 nil
.
我知道这并没有严格回答问题。但是你可以只使用 valueForKeypath
:
let fum = dict.valueForKeyPath("fee.fi.fo")
我一直在研究递归函数,以从表示为 NSDictionary 的 JSON 数据中提取字符串值。该函数允许您这样做:
if let value = extractFromNestedDictionary(["fee" : ["fi" : ["fo" : "fum"]]], withKeys: ["fee", "fi", "fo"]) {
println("\(value) is the value after traversing fee-fi-fo");
}
函数实现如下所示:
// Recursively retrieves the nested dictionaries for each key in `keys`,
// until the value for the last key is retrieved, which is returned as a String?
func extractFromNestedDictionary(dictionary: NSDictionary, withKeys keys: [String]) -> String? {
if keys.isEmpty { return nil }
let head = keys[0]
if let result: AnyObject = dictionary[head] {
if keys.count == 1 {
return result as? String
} else {
let tail: [String] = Array(keys[1..<keys.count])
if let result = result as? NSDictionary {
return extractFromNestedDictionary(result, withKeys: tail)
} else {
return nil
}
}
} else {
return nil
}
}
在 Swift 1.2/2.x 中是否有一些与可选绑定相关的语法特征可以:
- 让这个功能更简洁
- 少用
if
嵌套
我本来不想在没有你先尝试的情况下就成功的,但我还是做了,因为我喜欢 Swift 并且很开心:
func extractFromNestedDictionary(dictionary: [NSObject : AnyObject], var withKeys keys: [String]) -> String? {
if let head = keys.first, result = dictionary[head] {
if keys.count == 1 {
return result as? String
} else if let result = result as? [NSObject : AnyObject] {
keys.removeAtIndex(0)
return extractFromNestedDictionary(result, withKeys: keys)
}
}
return nil
}
extractFromNestedDictionary(["A" : ["B" : ["C" : "D"]]], withKeys: ["A", "B", "C"])
一些注意事项:
- 尽量避免使用
NSDictionary
并使用[NSObject : AnyObject]
代替,它无论如何都可以桥接到 NSDictionary 并且更 Swifty - 问问题的时候,试着举一个比你在那里做的更好的例子,从你的例子中我无法知道你到底想做什么。
这是我想出的最好的...
func extractFromNestedDictionary(dictionary: [NSObject : AnyObject], withKeys keys: [String]) -> String? {
if let head = keys.first,
result = dictionary[head] as? String
where keys.count == 1 {
return result
} else if let head = keys.first,
result = dictionary[head] as? [NSObject : AnyObject] {
return extractFromNestedDictionary(result, withKeys: Array(keys[1..<keys.count]))
}
return nil
}
您可以在 keys
数组上使用 reduce
而不是递归
遍历字典:
func extractFromNestedDictionary(dictionary: NSDictionary, withKeys keys: [String]) -> String? {
return reduce(keys, dictionary as AnyObject?) {
([=10=] as? NSDictionary)?[]
} as? String
}
在闭包内部,[=13=]
是当前级别的(可选)对象,</code>
当前密钥。闭包return是下一层的对象
如果 <code>[=13=]
是一个字典 and 有当前键的值,
nil
否则。 reduce()
的 return 值是
最后一层的对象或 nil
.
我知道这并没有严格回答问题。但是你可以只使用 valueForKeypath
:
let fum = dict.valueForKeyPath("fee.fi.fo")