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

时间:2017-01-07 06:20:03

标签: arrays swift dictionary swift3

汇总传递给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)
  

'?不限'不能转换为'数组< _>&#39 ;;你的意思是使用' as!'迫使低垂?

     

不能在类型'数组< _>'

的不可变值上使用变异成员

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

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

5 个答案:

答案 0 :(得分:14)

data[Items]的类型不是Array,而是实际Array<[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
}

答案 1 :(得分:4)

带有subscript

Dictionary始终返回optional(?)个实例,因为key中可能不存在Dictionary。现在您已将字典声明为[String:Any],表示key的类型为StringvalueAny

现在当您编写data["item"]时,它将返回不是数组的Any?,因此您无法调用append并且它将返回不可变值,因此您无法直接变异它

因此,您需要将其强制转换为Array of Dictionary并将其存储到实例中,然后追加该实例,然后使用重新分配替换字典中的该对象。

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) 
}

答案 2 :(得分:4)

如果您希望简洁而不是清晰度,则可以在一行中执行此操作,使用nil合并运算符和the + operator for RangeReplaceableCollectionArray符合的),后者用于&#34;追加&#34; step(事实上构建一个新的集合,在替换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 :(得分:0)

给你Array items:[String]

他也可以将此添加到json

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

data["items"] = items

答案 4 :(得分:0)

我不确定这是否适用于[String:Any]类型的字典,但是我也强烈建议您创建一个结构,而不要为字典使用“ Any”。这样可以使运行过程更加顺畅。

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

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

这将为将在字典中使用的“键”初始化一个数组,如果尚未初始化的话。没有这个,您将不得不自己检查并初始化数组,最终导致一些重复的代码。

希望这会有所帮助。