如何在给定 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"];

但我会质疑整个嵌套词典的概念;在我看来,你在这里走错了路,你需要退后一步,重新考虑你的数据结构。