如何轻松地向字典中的数组添加元素?

var dict = Dictionary<String, Array<Int>>()
dict["key"] = [1, 2, 3]

// all of these fail
dict["key"] += 4
dict["key"].append(4) // xcode suggests dict["key"].?.append(4) which also fails
dict["key"]!.append(4)
dict["key"]?.append(4)

// however, I can do this:
var arr = dict["key"]!
arr.append(4) // this alone doesn't affect dict because it's a value type (and was copied)
dict["key"] = arr

如果我只是将数组分配给一个变量,修改它,然后将其重新分配给dict,我不是在复制所有内容吗?这既不高效也不优雅.

推荐答案

Swift beta 5增加了这一功能,您在几次try 中就已经掌握了这一新方法.展开运算符!?现在将值传递给运算符或方法调用.也就是说,您可以通过以下任何方式向该数组中添加:

dict["key"]! += [4]
dict["key"]!.append(4)
dict["key"]?.append(4)

和往常一样,要注意使用哪种运算符——强制展开字典中没有的值会导致运行时错误:

dict["no-key"]! += [5]        // CRASH!

然而,使用可选链接将以静默方式失败:

dict["no-key"]?.append(5)     // Did it work? Swift won't tell you...

理想情况下,您可以使用新的空合并运算符??来处理第二种情况,但现在这不起作用.


Answer from pre-Swift beta 5:

这是Swift 的一个怪癖,你不可能做你想做的事.问题是,任何可选变量的value实际上都是一个常数——即使在强制展开时也是如此.如果我们只定义一个可选数组,下面是我们可以做的和不能做的:

var arr: Array<Int>? = [1, 2, 3]
arr[0] = 5
// doesn't work: you can't subscript an optional variable
arr![0] = 5
// doesn't work: constant arrays don't allow changing contents
arr += 4
// doesn't work: you can't append to an optional variable
arr! += 4
arr!.append(4)
// these don't work: constant arrays can't have their length changed

使用字典时遇到问题的原因是,订阅字典会返回一个可选值,因为无法保证字典将具有该键.因此,字典中的数组与上面的可选数组具有相同的行为:

var dict = Dictionary<String, Array<Int>>()
dict["key"] = [1, 2, 3]
dict["key"][0] = 5         // doesn't work
dict["key"]![0] = 5        // doesn't work
dict["key"] += 4           // uh uh
dict["key"]! += 4          // still no
dict["key"]!.append(4)     // nope

如果需要更改字典中数组中的某个内容,则需要获取该数组的副本,进行更改,然后重新分配,如下所示:

if var arr = dict["key"] {
    arr.append(4)
    dict["key"] = arr
}

ETA:同样的技术也适用于Swift beta 3,不过常量数组不再允许更改内容.

Swift相关问答推荐

格式化单位和度量值.为什么从符号初始化的单位不能产生与静态初始化相同的结果

我正在try 通过代码设置节中页眉和页脚的高度,但它不起作用

Swift通过设置变量B自动设置变量A的值

如何使 onKeyPress 与 TextField 快速配合使用?

为什么变量不存储在 Swift 的过程数据区中

为什么自定义串行队列的目标是全局队列时,Swift中不会并发执行?

是否可以利用 Codable 从 Dictionary 初始化符合类型

PassthroughSubject 的 AsyncPublisher 值属性未生成所有值

我怎样才能缩短(提高效率)这段代码?

为什么 String.contains 在我导入 Foundation 时表现不同?

Swift UI 不重绘 NSViewRepresentable 包装的文本字段

使 Swift 并发中的任务串行运行

Xcode:方法参数的代码完成

如何使被拖动的对象成为前景(foreground)对象

找不到接受提供的参数的/的重载

在 Swift 中将两个字节的 UInt8 数组转换为 UInt16

iOS Swift - 如何更改表格视图的背景 colored颜色 ?

在 Swift 中计算两个日期之间的差异

Swift 4 Decodable - 以枚举为键的字典

用 UIBezierPath 画一条线