Swift 迅捷迅捷,适用于';添加到数组,如果没有,则创建…';
我注意到Swift中的一个常见模式是Swift 迅捷迅捷,适用于';添加到数组,如果没有,则创建…';,swift,Swift,我注意到Swift中的一个常见模式是 var x:[String:[Thing]] = [:] 因此,当您想“向其中一个数组添加一个项”时,您不能 x[which].append(t) 你必须 if x.index(forKey: which) == nil { x[which] = [] } x[which]!.append(s!) 真的,有没有更快捷的方式来表达这样的意思 x[index?!?!].append??(s?!) 虽然这是一个关于风格的问题,由于Sw
var x:[String:[Thing]] = [:]
因此,当您想“向其中一个数组添加一个项”时,您不能
x[which].append(t)
你必须
if x.index(forKey: which) == nil {
x[which] = []
}
x[which]!.append(s!)
真的,有没有更快捷的方式来表达这样的意思
x[index?!?!].append??(s?!)
- 虽然这是一个关于风格的问题,由于Swift的复制特性,在Swift中触摸阵列时,性能似乎是一个关键问题
(请注意,显然您可以为此使用扩展;这是一个关于快速性的问题。)Swift 4更新: 从Swift 4开始,字典有一个方法,因此
dict[key, default: []].append(newElement)
附加到已存在的数组或空数组。例如:
var dict: [String: [Int]] = [:]
print(dict["foo"]) // nil
dict["foo", default: []].append(1)
print(dict["foo"]) // Optional([1])
dict["foo", default: []].append(2)
print(dict["foo"]) // Optional([1, 2])
从Swift 4.1开始(目前处于测试阶段),速度也很快,
比较哈米什的评论
顺便说一句,这里有一个惊人的片段,用于在Swift中正确地将类放入字典中:我认为您不可能通过一个下标+追加调用(没有自定义扩展)实现这一点可能的方法,除了你所说的:
x[which]=(x[which]??[])+[s]
或如果x[which]?.append(s)==nil{x[which]=[s]}
。我假设以前有人问过这个问题,但目前找不到。两者都会复制阵列–请参阅以了解避免此问题的方法。将改善这种情况,但AFAIK仍然不允许您使用任何特殊的灵活语法来实现您想要的。@JoeBlowx[which]!。append(s!)
确实会创建数组的副本。问题是需要使用临时变量来保存给定键的展开值(无论是强制展开还是可选链)。它是附加到字典中的临时数组,然后重新插入到字典中。因为字典和临时数组都有一个对基础数组缓冲区的视图,所以在追加时将触发一个副本。@JoeBlow您可以轻松地用btw测试此行为,不过请注意,对于stdlib中的非可选下标返回,有可能将指向基础值的指针传递回调用方(通过mutableAddressWithNativeOwner
subscript访问器),允许直接突变。这将使SE-0154提案能够有效地执行字典值的直接突变:)最显著的结果是,如果你达到10/100000。。。您的方法:28零合并:32可选链接28删除和添加:0.76!
dict[key] = (dict[key] ?? []) + [elem]
if dict[key]?.append(elem) == nil {
dict[key] = [elem]
}
if let i = dict.index(forKey: key) {
dict.values[i].append(elem)
} else {
dict[key] = [key]
}
var array = dict.removeValue(forKey: key) ?? []
array.append(elem)
dict[key] = array
let numKeys = 1000
let numElements = 1000
do {
var dict: [Int: [Int]] = [:]
let start = Date()
for key in 1...numKeys {
for elem in 1...numElements {
if dict.index(forKey: key) == nil {
dict[key] = []
}
dict[key]!.append(elem)
}
}
let end = Date()
print("Your method:", end.timeIntervalSince(start))
}
do {
var dict: [Int: [Int]] = [:]
let start = Date()
for key in 1...numKeys {
for elem in 1...numElements {
dict[key] = (dict[key] ?? []) + [elem]
}
}
let end = Date()
print("Nil coalescing:", end.timeIntervalSince(start))
}
do {
var dict: [Int: [Int]] = [:]
let start = Date()
for key in 1...numKeys {
for elem in 1...numElements {
if dict[key]?.append(elem) == nil {
dict[key] = [elem]
}
}
}
let end = Date()
print("Optional chaining", end.timeIntervalSince(start))
}
do {
var dict: [Int: [Int]] = [:]
let start = Date()
for key in 1...numKeys {
for elem in 1...numElements {
var array = dict.removeValue(forKey: key) ?? []
array.append(elem)
dict[key] = array
}
}
let end = Date()
print("Remove and add:", end.timeIntervalSince(start))
}
Your method: 0.470084965229034
Nil coalescing: 0.460215032100677
Optional chaining 0.397282958030701
Remove and add: 0.160293996334076
Your method: 14.6810429692268
Nil coalescing: 15.1537700295448
Optional chaining 14.4717089533806
Remove and add: 1.54668599367142