【问题标题】:Swift update value inside Dictionary<String, Any> in an Array快速更新数组中 Dictionary<String, Any> 内的值
【发布时间】:2019-07-23 04:54:57
【问题描述】:

我有一个字典数组,就像这样

var myArray: [Dictionary&lt;String, Any&gt;] = [Dictionary&lt;String, Any&gt;]()

我在课堂上的某个地方添加了值,如下所示:

var myDict = Dictionary<String, Any>()
myDict["Id"] = "someUniqueId"
myDict["v1"] = -42
self.myArray.append(myDict)

然后我尝试像这样更新这个字典中的v1

self.myArray.first(where: { $0["Id"] == "someUniqueId" })?["v1"] = -56

但是,编译器告诉我:

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

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

更新 该字典不是强类型的,因为字典中的内容(类型和字段名)都由外部系统中的用户控制。例如。我们下载一些元数据,然后为这些动态数据渲染控件。

【问题讨论】:

  • 任何时候你说任何警钟都应该响起。这个带有 Id 和 v1 的东西应该是一个结构,这应该是该结构的一个数组。
  • "可以在 EXTERNAL 系统中使用他们想要的任何数据类型定义他们想要的字典中的任何字段名" 您提供的调用站点是一个示例,还是存在"Id" 硬编码?跨度>
  • 甚至 Any 都可以使用某些包装类型(例如具有关联值的枚举)删除,以仅支持特定类型。
  • 但是你会有一个支持的类型列表,你知道如何使用的类型。
  • @zaitsman “来自 c# 我仍然有点坚持集合是值类型。”如果将它们作为引用类型对它们有益,只需将它们包装在一个类中,就像 Joakim 在他的回答中显示的那样。

标签: swift


【解决方案1】:

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

var myArray = [NSMutableDictionary]()
var myDict = NSMutableDictionary()
myDict["Id"] = "someUniqueId"
myDict["v1"] = -42
myArray.append(myDict)
myArray.first(where: { $0["Id"] as? String == "someUniqueId" })?["v1"] = -56

print(myArray)
// [{
//     Id = someUniqueId;
//     v1 = "-56";
// }]

【讨论】:

  • 哎呀,我强烈建议不要这样做。 NSMutableDictionary 速度较慢,不是通用的,而且只是 Swift 中的一个全面糟糕的时间。
  • @Alexander 当然,这可能是一个不太“迅速”的解决方案。然而它完成了工作,这正是 OP 想要的。
【解决方案2】:

您可以通过将字典包装在一个简单的类中来让自己更轻松

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 这样的类,并保持它更纯粹的 Swift。自定义类的另一个优点是您可以为其添加功能以简化使用它的代码,例如,如果您将通过“Id”查找字典很多,我们可以为其添加计算属性

var id: String? {
    return valueFor("Id") as? String
}

然后上面的例子就变成了

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

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-02-02
  • 2017-06-07
  • 2017-02-27
  • 1970-01-01
  • 2020-03-07
  • 2016-04-26
  • 2020-03-23
相关资源
最近更新 更多