如何轻松地将元素添加到字典中的数组?它总是抱怨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,我不会复制所有内容吗?这不会有效也不优雅。
投票
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...
理想情况下,您可以使用新的空合并运算符??
来解决第二种情况,但是现在它无法正常工作。
来自Swift beta 5之前的答案:
这是斯威夫特的一个怪癖,你不可能做你想做的事情。问题是任何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中有效,尽管常量数组不再允许更改内容。
投票
作为一个简单的解决方法,您可以使用NSMutableArray:
import Foundation
var dict = Dictionary<String, NSMutableArray>()
dict["key"] = [1, 2, 3] as NSMutableArray
dict["key"]!.addObject(4)
我在我的项目中使用了这么简单的解决方案:
https://github.com/gui-dos/Guigna/blob/5c02f7e70c8ee3b2265f6916c6cbbe5cd3963fb5/Guigna-Swift/Guigna/GuignaAppDelegate.swift#L1150-L1157
投票
以下是我对Nate Cook所说的质量答案的评论。这就是我认为“轻松[添加]元素到字典中的数组”:
dict["key"] = dict["key"]! + 4
dict["key"] = dict["key"] ? dict["key"]! + 4 : [4]
现在,我们需要自己定义+运算符。
@infix func +<T>(array: T[], element: T) -> T[] {
var copy = array
copy += element
return copy
}
我认为这个版本删除了太多的安全性;也许用复合算子来定义它?
@infix func +<T>(array: T[]?, element: T) -> T[] {
return array ? array! + element : [element]
}
dict["key"] = dict["key"] + 4
最后,这是我能得到的最干净的,但我对这个例子中的数组值/引用如何工作感到困惑。
@assignment func +=<T>(inout array: T[]?, element: T) {
array = array + element
}
dict["key"] += 5
投票
接受的答案绕过了以下更简单的可能性,这也适用于较旧的Swift版本:
var dict = Dictionary<String, Array<Int>>()
dict["key"] = [1, 2, 3]
print(dict)
dict["key", default: [Int]()].append(4)
print(dict)
这将打印:
["key": [1, 2, 3]]
["key": [1, 2, 3, 4]]
还有这个:
var dict = Dictionary<String, Array<Int>>()
dict["key", default: [Int]()].append(4)
print(dict)
将打印:
["key": [4]]
投票
使用'for in',从字典的内部数组中获取值。这是一个帮助你的例子
var a = ["x":["a","b","c"], "y":["d"]]
for b in a {
print(b)
}
输出:
("x", ["d"])
("y", ["a", "b", "c"])