快速引用内部数组

Lan*_*kin 6 c# arrays jagged-arrays mutability swift

我来自C#世界,曾经习惯于将数组作为引用类型。据我了解,快速数组中的是值类型,但它们试图充当参考值。

我实际上不知道如何问自己需要什么(我认为这是当我需要知道答案才能提出问题时的情况),但是在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]]
Run Code Online (Sandbox Code Playgroud)

Swift沙箱(http://swiftlang.ng.bluemix.net/#/repl/8608824e18317e19b32113e1aa08deeb4ec5ab96ed8cdbe1dbfb4e753e87d528

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

在选项(1)中,我将所有内容都更改为“ -1”,并且可以使用,但是为此使用了其他功能。

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

如何获得类似于选项(1)的结果,但是使用局部变量而不是函数?也就是说,如何获取对内部数组的引用并将其放入局部变量?

我会理解“没有办法”的答案,但是我希望这样的答案能与一些Apple裁判一起提供。

Aar*_*sen 1

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

\n
\n

值类型最基本的区别特征是复制 \xe2\x80\x94 赋值、初始化和参数传递 \xe2\x80\x94 的效果会创建一个独立的实例,该实例具有其数据的唯一副本。

\n
\n

和这里

\n
\n

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

\n

[...]

\n

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

\n
\n

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

\n

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

\n
// (2) Creates local copy\nvar r = matrix[rowIdx]   \nprocessRow(&r, -2)\nmatrix[rowIdx] = r\n
Run Code Online (Sandbox Code Playgroud)\n

与您建议的最接近的是使用指针:UnsafeMutablePointerUnsafePointer等。但这确实违背了 Swift 的设计使用方式。然而,如果你愿意的话,它看起来会像这样:

\n
func processRow(ptr: UnsafeMutablePointer<Int>, _ value : Int, count: Int) {\n    for col in 0..<count {\n        ptr.advancedBy(col).memory = value\n    }\n}\n\nfunc processMatrix(inout matrix : [[Int]]) {\n    for rowIdx in 0..<matrix.count {\n        \n        let r = UnsafeMutablePointer<Int>(matrix[rowIdx])\n        processRow(r, -2, count: matrix[rowIdx].count)\n    }\n}\n\nvar matrix = [\n    [1, 2, 3],\n    [4, 5, 6],\n    [7, 8, 9]\n]\n\nprocessMatrix(&matrix)\nprint(matrix)   // [[2, 2, 2], [2, 2, 2], [2, 2, 2]]\n
Run Code Online (Sandbox Code Playgroud)\n

  • 我确实理解值类型。我只是不接受数组作为值类型。我看不出有什么理由将数组作为一个整体传递而不是对其的引用;苹果似乎也是如此,因为他们实际上在内部这样做了,但似乎他们必须玩这个游戏才能满足他们的 let / var 容器.. (2认同)