如何在给定 Swift 中的路径片段的情况下更新嵌套字典中的值?
How to update a value in a nested dictionary given path fragment in Swift?
我有一个嵌套字典和一个包含路径片段的数组。我需要更新那个位置的值。
我可能正在寻找递归函数而不是 Dictionary
类型等的扩展。
我无法递归执行此操作,因为我复制了 inout
参数。
var dict: [String: Any] = ["channel": ["item": ["title": 1111]]]
var pathFrag = ["channel", "item", "title"]
var val = 123
func addAt(pathFrag: inout [String], val: Int, data: inout [String: Any]) {
if let first = pathFrag.first {
if let item = data[first] {
print(item)
pathFrag.remove(at: 0)
if !pathFrag.isEmpty {
var d: [String: Any] = data[first] as! [String: Any]
print("e: \(d)")
return addAt(pathFrag: &pathFrag, string: string, data: &d)
} else {
data[first] = val
print("else: \(data)") // ["title": 123]
}
}
}
}
addAt(pathFrag: &pathFrag, val: val, data: &dict)
print(dict)
如何将title
的值更新为123
?
请注意,var d: [String: Any] = data[first] as! [String: Any]
复制了 data[first]
,而不是像 &
和 inout
那样引用它。因此,当 addAt(pathFrag: &pathFrag, string: string, data: &d)
被调用时,只有 d
被改变。要使此更改反映在原始 data[first]
上,您必须将 d
分配回 data[first]
。
这样做:
var dict: [String: Any] = ["channel": ["item": ["title": 1111]]]
var pathFrag = ["channel", "item", "title"]
func addAt(pathFrag: inout [String], data: inout [String: Any]) {
if let first = pathFrag.first {
if let item = data[first] {
pathFrag.remove(at: 0)
if !pathFrag.isEmpty {
var d: [String: Any] = data[first] as! [String: Any]
addAt(pathFrag: &pathFrag, data: &d)
data[first] = d
} else {
data[first] = 123
}
}
}
}
addAt(pathFrag: &pathFrag, data: &dict)
print(dict)
这不是你问的,但这里的整个前提是 unSwifty。 [String:Any]
的使用是一种难闻的气味。看起来更像是Objective-C。事实上,这整个事情是 Objective-C:
中的一行
NSMutableDictionary * d1 = [[NSMutableDictionary alloc] initWithDictionary: @{ @"title" : @1111 }];
NSMutableDictionary * d2 = [[NSMutableDictionary alloc] initWithDictionary: @{ @"item" : d1 }];
NSMutableDictionary * d3 = [[NSMutableDictionary alloc] initWithDictionary: @{ @"channel" : d2 }];
好的,那只是准备数据。这是一条线:
[d3 setValue:@123 forKeyPath:@"channel.item.title"];
但我会质疑整个嵌套词典的概念;在我看来,你在这里走错了路,你需要退后一步,重新考虑你的数据结构。
我有一个嵌套字典和一个包含路径片段的数组。我需要更新那个位置的值。
我可能正在寻找递归函数而不是 Dictionary
类型等的扩展。
我无法递归执行此操作,因为我复制了 inout
参数。
var dict: [String: Any] = ["channel": ["item": ["title": 1111]]]
var pathFrag = ["channel", "item", "title"]
var val = 123
func addAt(pathFrag: inout [String], val: Int, data: inout [String: Any]) {
if let first = pathFrag.first {
if let item = data[first] {
print(item)
pathFrag.remove(at: 0)
if !pathFrag.isEmpty {
var d: [String: Any] = data[first] as! [String: Any]
print("e: \(d)")
return addAt(pathFrag: &pathFrag, string: string, data: &d)
} else {
data[first] = val
print("else: \(data)") // ["title": 123]
}
}
}
}
addAt(pathFrag: &pathFrag, val: val, data: &dict)
print(dict)
如何将title
的值更新为123
?
请注意,var d: [String: Any] = data[first] as! [String: Any]
复制了 data[first]
,而不是像 &
和 inout
那样引用它。因此,当 addAt(pathFrag: &pathFrag, string: string, data: &d)
被调用时,只有 d
被改变。要使此更改反映在原始 data[first]
上,您必须将 d
分配回 data[first]
。
这样做:
var dict: [String: Any] = ["channel": ["item": ["title": 1111]]]
var pathFrag = ["channel", "item", "title"]
func addAt(pathFrag: inout [String], data: inout [String: Any]) {
if let first = pathFrag.first {
if let item = data[first] {
pathFrag.remove(at: 0)
if !pathFrag.isEmpty {
var d: [String: Any] = data[first] as! [String: Any]
addAt(pathFrag: &pathFrag, data: &d)
data[first] = d
} else {
data[first] = 123
}
}
}
}
addAt(pathFrag: &pathFrag, data: &dict)
print(dict)
这不是你问的,但这里的整个前提是 unSwifty。 [String:Any]
的使用是一种难闻的气味。看起来更像是Objective-C。事实上,这整个事情是 Objective-C:
NSMutableDictionary * d1 = [[NSMutableDictionary alloc] initWithDictionary: @{ @"title" : @1111 }];
NSMutableDictionary * d2 = [[NSMutableDictionary alloc] initWithDictionary: @{ @"item" : d1 }];
NSMutableDictionary * d3 = [[NSMutableDictionary alloc] initWithDictionary: @{ @"channel" : d2 }];
好的,那只是准备数据。这是一条线:
[d3 setValue:@123 forKeyPath:@"channel.item.title"];
但我会质疑整个嵌套词典的概念;在我看来,你在这里走错了路,你需要退后一步,重新考虑你的数据结构。