7

我来自 C# 世界,习惯于将数组作为引用类型。据我了解,在 swift 数组中是值类型,但它们试图作为参考值类型。

我实际上不知道如何问我需要什么(我认为当我需要知道答案才能提出问题时就是这种情况),但在 C# 中我会说我需要存储对 a 的内部数组的引用将锯齿状数组转换为局部变量。

考虑以下代码:

// a function to change row values in-place
func processRow(inout row : [Int], _ value : Int)
{
    for col in 0..<row.count
    {
        row[col] = value;
    }
}

// a function to change matrix values in-place
func processMatrix(inout matrix : [[Int]])
{
    for rowIdx in 0..<matrix.count
    {
        // (1) Works with array in-place
        processRow(&(matrix[rowIdx]), -1)

        // (2) Creates local copy
        var r = matrix[rowIdx]; // <--- What to write here to not make a copy but still have this local variable?
        processRow(&r, -2);
    }
}

var matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

processMatrix(&matrix)

print(matrix) // outputs [[-1, -1, -1], [-1, -1, -1], [-1, -1, -1]]

此处为 Swift 沙箱http://swiftlang.ng.bluemix.net/#/repl/8608824e18317e19b32113e1aa08deeb4ec5ab96ed8cdbe1dbfb4e753e87d528

在这里,我想就地处理多维数组,这样我就不会创建数组的副本或数组的一部分。

在选项(1)中,我将所有内容更改为“-1”,它可以工作,但为此使用了附加功能。

在选项(2)中,我尝试使用局部变量来存储matrix[rowIdx],但它实际上创建了内部数组的副本——不是我想要的;使用此变量会更改数组的副本,而不是原始的。

我怎样才能达到选项(1)中的结果,但使用局部变量而不是函数?也就是说,如何获取对内部数组的引用并将其放入局部变量?

我会理解答案“这是不可能的”,但我希望这些答案伴随着一些 Apple 参考。

4

2 回答 2

1

我不相信有一种方法可以在不复制的情况下将数组复制到局部变量中。这正是值类型在 Swift 中的工作方式。苹果说

值类型最基本的区别特征是复制——赋值、初始化和参数传递的效果——创建一个独立的实例,它有自己唯一的数据副本[.]

在这里

值类型是一种类型,其值在分配给变量或常量或传递给函数时被复制...

[...]

Swift 中的所有结构和枚举都是值类型。这意味着您创建的任何结构和枚举实例——以及它们作为属性的任何值类型——在它们在代码中传递时总是被复制。

它只是值类型定义的一部分——每个数组都是一个值类型。

获得所需结果的最简单方法是将 的值重新分配r给要更改的行matrix

// (2) Creates local copy
var r = matrix[rowIdx]   
processRow(&r, -2)
matrix[rowIdx] = r

与您的建议最接近的是使用指针:UnsafeMutablePointer,UnsafePointer等。但这确实与 Swift 的设计使用方式作斗争。但是,如果您愿意,它看起来像这样:

func processRow(ptr: UnsafeMutablePointer<Int>, _ value : Int, count: Int) {
    for col in 0..<count {
        ptr.advancedBy(col).memory = value
    }
}

func processMatrix(inout matrix : [[Int]]) {
    for rowIdx in 0..<matrix.count {
        
        let r = UnsafeMutablePointer<Int>(matrix[rowIdx])
        processRow(r, -2, count: matrix[rowIdx].count)
    }
}

var matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

processMatrix(&matrix)
print(matrix)   // [[2, 2, 2], [2, 2, 2], [2, 2, 2]]
于 2016-01-18T22:39:31.070 回答
1

Swift 数组在处理可变数据时非常痛苦。有两种方法可以解决这个问题:

1) 使用 NSMutableArray

import Foundation

func processRow(_ row : NSMutableArray, _ value : Int) {
    for col in 0..<row.count {
        row[col] = value;
    }
}

func processMatrix(_ matrix : inout [NSMutableArray]) {
    for rowIdx in 0..<matrix.count {
        let r = matrix[rowIdx]
        processRow(r, -2);
    }
}

var matrix = [
    NSMutableArray(array: [1, 2, 3]),
    NSMutableArray(array: [4, 5, 6]),
    NSMutableArray(array: [7, 8, 9])
]

processMatrix(&matrix)

print(matrix) // outputs , <__NSArrayM 0x6000027a1560>(-2,-2,-2)]

2)使用类包装器

class Wrapper<T: CustomDebugStringConvertible>: CustomDebugStringConvertible {
    var value: T

    init(_ value: T) {
        self.value = value
    }

    var debugDescription: String {
        return value.debugDescription
    }
}

func processRow(_ row : Wrapper<[Int]>, _ value : Int) {
    for col in 0..<row.value.count {
        row.value[col] = value;
    }
}

func processMatrix(_ matrix : inout [Wrapper<[Int]>]) {
    for rowIdx in 0..<matrix.count {
        let r = matrix[rowIdx]
        processRow(r, -2);
    }
}

var matrix = [
    Wrapper([1, 2, 3]),
    Wrapper([4, 5, 6]),
    Wrapper([7, 8, 9])
]

processMatrix(&matrix)

print(matrix) // outputs [[-2, -2, -2], [-2, -2, -2], [-2, -2, -2]]

然而它看起来不是很好。

于 2019-04-12T18:54:01.837 回答