在[String:Any]字典结构中附加到数组

Jas*_*ges 13 arrays dictionary swift swift3

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

我的数据结构开始于:

var data: [String: Any] = [
    "key1": "example value 1",
    "key2": "example value 2",
    "items": [
        // I need to append here later
    ]
]
Run Code Online (Sandbox Code Playgroud)

items密钥对的集合,我需要一个循环内后追加.

要添加到data["items"]数组,我正在尝试这样的事情:

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

    data["items"].append(item)
}
Run Code Online (Sandbox Code Playgroud)

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

这是有道理的,因为我需要将值转换为追加; 但是,我无法改变阵列.

转换为数组,无论是强制向下转换都会产生错误:

(data["items"] as! Array).append(item)
Run Code Online (Sandbox Code Playgroud)

'任何?' 不能转换为'Array <_>'; 你的意思是用'as!' 迫使低垂?

不能在类型为"Array <_>"的不可变值上使用变异成员

好像我的演员是错的; 或者,也许我会以错误的方式解决这个问题.

关于如何data["items"]随着时间的推移迭代填充的任何建议?

Mat*_*ewS 15

实际上data[Items]不是这种类型.ArrayArray<[String: Any]>

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

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
}
Run Code Online (Sandbox Code Playgroud)


Nir*_*v D 5

subscriptDictionary总是返回optional(?)实例,因为它可能可能key不存在Dictionary。现在你已经将你的字典声明[String:Any]keyisStringvalueis 的手段类型Any

现在,当您编写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
}
Run Code Online (Sandbox Code Playgroud)

如果你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) 
}
Run Code Online (Sandbox Code Playgroud)

  • @dfri Thnx 的建议,您为 OP 问题提供了完美的解决方案。 (2认同)

dfr*_*fri 5

如果您希望简洁而不是简洁,则可以在一行中执行此操作,利用nil合并运算符和+运算符RangeReplaceableCollectionArray符合),后者用于“追加”步骤(实际上是构造一个新集合,替换的值时,将替换现有的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"]       */
Run Code Online (Sandbox Code Playgroud)