Swift 字典内的快速更新值<;字符串,任意>;排列

Swift 字典内的快速更新值<;字符串,任意>;排列,swift,Swift,我有一系列字典,就像这样 var myArray:[字典]=[字典]() 我在班上的某个地方添加了一些值,如下所示: var myDict=Dictionary() myDict[“Id”]=“某个唯一Id” myDict[“v1”]=-42 self.myArray.append(myDict) 然后,稍后我尝试更新此dict中的v1,如下所示: self.myArray.first(where: { $0["Id"] == "someUniqueId" })?["v1"] = -56 但

我有一系列字典,就像这样

var myArray:[字典]=[字典]()

我在班上的某个地方添加了一些值,如下所示:

var myDict=Dictionary()
myDict[“Id”]=“某个唯一Id”
myDict[“v1”]=-42
self.myArray.append(myDict)
然后,稍后我尝试更新此dict中的
v1
,如下所示:

self.myArray.first(where: { $0["Id"] == "someUniqueId" })?["v1"] = -56
但是,编译器告诉我:

无法通过下标赋值:函数调用返回不可变值

除了复制整个字典、将其从数组中删除并重新插入之外,还有什么方法可以修改数组中的值


更新此词典不是强类型词典,因为词典中的类型和字段名都由外部系统中的用户控制。例如,我们下载一些元数据,然后呈现此动态数据的控件。

这是因为Swift Dictionary是一种值类型。 使用自定义类,或者为此目的可以使用
NSMutableDictionary
(因为
NSDictionary
是不可变的)


您可以通过将字典包装在一个简单的类中来简化它

class Config {
    private var dict: [String: Any]

    init(_ dict: [String: Any]) {
        self.dict = dict
    }

    func valueFor(_ key: String) -> Any? {
        return dict[key]
    }

    func setValue(_ value: Any, forKey key: String) {
        dict[key] = value
    }
}
并在数组中使用它

var myArray = [Config]()
像这样使用它

array.filter { $0.valueFor("Id") as? String == "someUniqueId" }
    .first?.setValue(-56, forKey: "v1")
这样可以避免使用NSMutableDictionary之类的类,并使其更加简洁。自定义类的另一个优点是,您可以向它添加功能,以简化使用它的代码,因此,例如,如果您将大量使用“Id”查找字典,那么我们可以为它添加计算属性

var id: String? {
    return valueFor("Id") as? String
}
然后上面的例子就会变成

array.filter { $0.id == "someUniqueId" }.first?.setValue(-56, forKey: "v1")

你说什么时候警铃都会响。带有Id和v1的东西应该是一个结构,这应该是该结构的一个数组。“在外部系统中,可以用他们想要的任何数据类型在这个字典中定义他们想要的任何字段名”是您提供的调用站点示例,还是存在
“Id”
硬编码?甚至可以使用某种包装类型删除任何字段名,例如,一个带有关联值的枚举,只支持特定类型。但是你会有一个受支持类型的列表,你知道如何使用这些类型。@zaitsman“来自c#我仍然有点坚持认为集合是值类型。”如果它们是引用类型对它们有利,只需将它们包装在一个类中,就像Joakim在他的回答中所表现的那样。哎呀,我建议你不要这样做
NSMutableDictionary
速度较慢,不是通用的,而且在Swift中是一个全面的糟糕时刻。@Alexander:当然,这可能是一个不太“快速”的解决方案。但它完成了任务,这正是OP想要的。我只能看到:
array.filter { $0.id == "someUniqueId" }.first?.setValue(-56, forKey: "v1")