【问题标题】:How to deeply duplicate a multidimensional array in Swift如何在 Swift 中深度复制多维数组
【发布时间】:2016-05-06 22:01:09
【问题描述】:

已经针对其他几种编码语言提出并回答了这个问题,但我认为我可能有一个独特的问题。所以,我想复制一个三维数组(填充任意对象)。我相信我发现了这一点:

var duplicateArray = originalArray

不起作用,因为无论出于何种原因,他们认为让它创建一个重复数组是一个很好的安全措施,但将指针作为子数组填充,而不是复制子数组。这似乎是一个奇怪的设计选择,因为如果 duplicateArray 和 originalArray 是一维的,这将按预期工作。无论如何,所以我尝试了这个(其中对象是一些任意对象):

var duplicateArray = [[[object]]]()
for x in 0..<originalArray.count {
    var tempArrYZ = [[object]]()
    for y in 0..<originalArray[x].count {
        var tempArrZ = [object]()
        for z in 0..<originalArray[x][y].count {
            let copiedObj = originalArray[x][y][z]
            tempArrZ.append(copiedObj)
        }
        tempArrYZ.append(tempArrZ)
    }
    duplicateArray.append(tempArrYZ)
}

这仍然不起作用; duplicateArray 中的所有值都将充当指向它们在 originalArray 中的值的指针。也许有人有一个简单的方法来深度复制多维数组,或者也许有人能找到我的错误?

编辑:这与其他问题有何重复?我在问具体如何“深度”复制。关于复制数组的问题模糊不清。

【问题讨论】:

  • 请注意,初始化和附加到数组的成本很高,因为它可能涉及多次调整大小操作(这些操作本身需要对数组进行完整复制)。当你知道时,用你需要的大小初始化数组。
  • 是的,正如所指出的,如果值是值类型,它们会被复制到带有var duplicateArray = originalArray 的新数组中,如果有对象,它们的引用会被复制。不确定那些不明白这一点的人是否会要求对 swift 进行批评......

标签: swift multidimensional-array duplicates


【解决方案1】:
var duplicateArray = originalArray

如果对象不是引用类型,则可以使用。但是,对于引用类型,您需要使用copy 实际创建对象的副本。您的原始代码非常接近。

var duplicateArray = [[[object]]]()
for x in 0..<originalArray.count {
    var tempArrYZ = [[object]]()
    for y in 0..<originalArray[x].count {
        var tempArrZ = [object]()
        for z in 0..<originalArray[x][y].count {
            let copiedObj = originalArray[x][y][z].copy()
            tempArrZ.append(copiedObj)
        }
        tempArrYZ.append(tempArrZ)
    }
    duplicateArray.append(tempArrYZ)
}

【讨论】:

    【解决方案2】:

    如前所述,您的问题实际上不是数组的复制,而是对象的复制。与所有结构一样,数组是按值复制的。对象是通过引用复制的。

    当您复制对象数组时,它是一个全新的数组,其中包含对所包含对象的全新引用。您的代码只是创建对相同对象的附加引用,然后以类似的方式组织它们。

    无论如何,这是我复制数组的更简单/功能性的实现:

    func copyArrayWithObjects <T: Copying>(items: [T]) -> [T]{
        return items.map { $0.copy() }
    }
    
    func copy2DArrayWithObjects <T: Copying>(items: [[T]]) -> [[T]] {
        return items.map(copyObjectsInArray)
    }
    
    func copy3DArrayWithObjects<T: Copying>(items: [[[T]]]) -> [[[T]]] {
        return items.map(copy2DObjectInArray)
    }
    

    那么你可以简单地这样做:

    let copiedArray = copy3DArrayWithObjects(originalArray)
    

    理论上我认为可以为 n 维数组创建一个函数来执行此操作,但我还没有找到解决方案。

    【讨论】:

      【解决方案3】:

      我认为最好在 Array 上编写一个扩展,以增加对 NSCopying 的一致性,它递归地复制元素。这个解决方案会非常优雅,因为它可以扩展到任意数量的维度。

      【讨论】:

        【解决方案4】:

        Swift 数组是值类型,所以你提供的 sn-p 很好。

        var duplicateArray = originalArray
        

        在 Playground 中查看此示例作为证明:

        var array = [[["test"]]]
        var newarray = array
        
        // print different memory addresses
        
        print(unsafeAddressOf(array[0][0][0])) // 0x00007ff7a302a760
        print(unsafeAddressOf(newarray[0][0][0])) // 0x00007ff7a33000e0
        

        如果您在 Swift 数组中使用 NSArray 或引用类型,那么它们将不再隐式复制,并且将使用相同的地址处理 - 这也可以在 Playground 中得到证明。您需要在引用类型上显式调用 copy()

        【讨论】:

        • Swift 中的字符串是值类型,因此在这种情况下它们总是被复制developer.apple.com/library/ios/documentation/Swift/Conceptual/…
        • @RomanTsegelskyi 我知道字符串是值类型。如果您使用引用类型或您不会复制的 NSArray,我会在我的回答中明确说明。作者没有提到他使用的是引用类型还是值类型。我添加了一个小说明,但不确定为什么会有反对票。
        猜你喜欢
        • 2010-09-17
        • 1970-01-01
        • 1970-01-01
        • 2012-06-26
        • 2014-09-05
        • 2010-09-30
        • 2020-03-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多