Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 迅捷迅捷,适用于';添加到数组,如果没有,则创建…';_Swift - Fatal编程技术网

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

我注意到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?!)
  • 虽然这是一个关于风格的问题,由于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仍然不允许您使用任何特殊的灵活语法来实现您想要的。@JoeBlow
x[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