【问题标题】:Append to array in [String: Any] dictionary structure追加到 [String: Any] 字典结构中的数组
【发布时间】:2017-05-21 23:18:37
【问题描述】:

组装传递给GRMustache.swift 以呈现胡子模板的数据有效负载,我需要将数据附加到字典中先前定义的数组中。

我的数据结构开始于:

var data: [String: Any] = [
    "key1": "example value 1",
    "key2": "example value 2",
    "items": [
        // I need to append here later
    ]
]

items 密钥对是我需要稍后在循环中附加的集合。

要添加到 data["items"] 数组,我正在尝试类似:

for index in 1...3 {
    let item: [String: Any] = [
        "key": "new value"
    ]

    data["items"].append(item)
}

此错误,因为Any? 类型的值没有成员append,并且二元运算符+= 不能应用于Any?[String : Any] 类型的操作数。

这是有道理的,因为我需要将值转换为追加;但是,我不能改变数组。

强制转换为数组,强制向下转换是否报错:

(data["items"] as! Array).append(item)

“有吗?”不能转换为 'Array<_>';你的意思是用'as!'强制沮丧?

不能对'Array<_>'类型的不可变值使用变异成员

好像我的演员表错了;或者,也许我以错误的方式处理这个问题。

关于如何随时间迭代地填写data["items"] 有什么建议吗?

【问题讨论】:

    标签: arrays swift dictionary swift3


    【解决方案1】:

    data[Items] 的类型不是Array,而是实际上Array&lt;[String: Any]&gt;

    您可以将其压缩为更少的步骤,但我更喜欢多个步骤的清晰性:

    var data: [String: Any] = [
        "key1": "example value 1",
        "key2": "example value 2",
        "items": []
    ]
    
    for index in 1...3 {
    
        let item: [String: Any] = [
            "key": "new value"
        ]
    
        // get existing items, or create new array if doesn't exist
        var existingItems = data["items"] as? [[String: Any]] ?? [[String: Any]]()
    
        // append the item
        existingItems.append(item)
    
        // replace back into `data`
        data["items"] = existingItems
    }
    

    【讨论】:

    • 如果我们的数据是 [[String: Any]] 怎么办?当我尝试它给我绑定异常的索引时! var params = [[String: Any]]() for i in 0..data.count - 1 { params = [["otherKey":otherValue, "products": [] ]] for j in 0...data [i].products.count - 1 { 让 item : [String: Any] = ["prodcutName": data[i].product[j].name] var existingItems = params[i]["products"] as? [[字符串:任何]] ?? [[String: Any]]() // 这里崩溃了!!! “索引超出范围” existingItems.append(item) params[i]["products"] = existingItems } }
    • 谢谢你,救了我的命。
    【解决方案2】:

    如果您更喜欢简洁而不是清晰,您可以在一行中执行此操作,使用 nil 合并运算符和 the + operator for RangeReplaceableCollection(与 Array 一致),后者用于“附加”步骤(实际上是构建一个新集合,在替换data["items"] 的值时将替换现有集合)。

    // example setup
    var data: [String: Any] = [
        "key1": "example value 1",
        "key2": "example value 2",
        "items": []
    ]
    
    // copy-mutate-replace the "items" array inline, adding a new dictionary
    data["items"] = (data["items"] as? [[String: Any]] ?? []) + [["key": "new value"]]
    
    print(data)
    /* ["key2": "example value 2", 
        "items": [["key": "new value"]], 
        "key1": "example value 1"]       */
    
    // add another dictionary to the "items" array
    data["items"] = (data["items"] as? [[String: Any]] ?? []) + [["key": "new value"]]
    
    print(data)
    /* ["key2": "example value 2",
     "items": [["key": "new value"], ["key": "new value"]],
     "key1": "example value 1"]       */
    

    【讨论】:

      【解决方案3】:

      subscriptDictionary 总是返回 optional(?) 实例,因为 key 可能不存在于 Dictionary 中。现在你已经将你的字典声明为[String:Any] 意味着key 的类型是StringvalueAny

      现在,当您编写 data["item"] 时,它会返回 Any?,这不是 Array,因此您不能调用 append,它会返回不可变的值,因此您不能直接对其进行变异。

      因此,您需要将其类型转换为字典数组并将其存储到实例并附加该实例,然后使用重新分配替换字典中的该对象。

      for index in 1...3 {
          let item: [String: Any] = [
              "key": "new value"
          ]
      
          var array = data["items"] as? [[String:Any]] ?? [[String:Any]]()
          array.append(item)
          data["items"] = array
      }
      

      如果你有 Dictionary[String: [[String:Any]]] 这样的例子,现在事情会变得容易得多。

      var data: [String: [[String:Any]]] = [
          "items": []
      ]
      
      for index in 1...3 {
          let item: [String: Any] = [
              "key": "new value"
          ]
          data["items"]?.append(item) 
      }
      

      【讨论】:

      • @JasonSturges 我知道,我刚刚向您展示了问题所在以及您可以在哪里直接附加字典中的数组。
      • 真的很欣赏[String: [[String: Any]]] 打字的清晰和优雅。
      • 请注意,您可以使用data["items"]?.append(item) 而不是上面的data["items"]!.append(item);如果"items" 键没有值(即使我们知道它在本例中),后者将产生运行时崩溃,而前者将简单地返回未使用的nil。即使我们知道存在"items" 密钥,我相信我们应该更喜欢安全的方法,尤其是在没有额外费用的情况下。对于没有意识到在这种特殊情况/示例中,! 是安全的,否则通常不安全的初学者 SO 读者,总是有加强不良 ! 实践的风险。
      • @dfri Thnx 提出建议,您为 OP 问题提供了完美的解决方案。
      【解决方案4】:

      我不完全确定这是否适用于 [String: Any] 类型的字典,但我也强烈建议您创建一个结构,而不是为您的字典使用“Any”。这将有助于使事情运行得更顺畅。

      另一方面,我想提一下,您可以尝试以下方法:

      yourDictionary["Key", default: []].append(item)
      

      如果还没有初始化数组,这将为字典中使用的“键”初始化一个数组。如果没有这个,您必须自己检查和初始化数组,这最终会成为一些重复的代码。

      希望这会有所帮助。

      【讨论】:

        【解决方案5】:

        给你一个Arrayitems:[String]

        他也可以把这个加到json里

        var items = ["string1", "Info 2","Text 4"]
        
        data["items"] = items
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-06-10
          • 2015-10-01
          • 1970-01-01
          • 1970-01-01
          • 2018-07-17
          • 1970-01-01
          • 2013-01-02
          • 1970-01-01
          相关资源
          最近更新 更多