一尘不染

迅捷:在字典中修改数组

swift

如何轻松将元素添加到字典中的数组?总是抱怨could not find member 'append'could not find an overload for '+='

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

如果我只是将数组分配给var,先对其进行修改,然后再将其重新分配给dict,我是否会复制所有内容?那既不会高效又不会优雅。


阅读 245

收藏
2020-07-07

共1个答案

一尘不染

Swift beta
5已添加了此功能,并且您在几次尝试中都采用了新方法。的解缠运营商!?现在穿过值要么运营商或方法调用。也就是说,您可以通过以下任何一种方式将其添加到该数组中:

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...

理想情况下,您将能够使用新的null合并运算符??来解决第二种情况,但是现在不起作用。


迅捷Beta 5之前的答案:

Swift的古怪之处在于,您不可能做自己想做的事情。问题是任何Optional变量的 实际上都是一个常数-
即使在强制展开时也是如此。如果我们仅定义一个Optional数组,这是我们可以做的和不能做的:

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

使用字典时遇到问题的原因是,对字典进行下标会返回一个Optional值,因为无法保证该字典将具有该键。因此,字典中的数组与上面的Optional数组具有相同的行为:

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中也有效,尽管常量数组不再允许更改内容。

2020-07-07