如何在C#中调整多维(2D)数组的大小?

Man*_*uel 29 c# arrays

我尝试了以下但它只是返回一个搞砸的数组.

    T[,] ResizeArray<T>(T[,] original, int rows, int cols)
    {
        var newArray = new T[rows,cols];
        Array.Copy(original, newArray, original.Length);
        return newArray;
    }
Run Code Online (Sandbox Code Playgroud)

Tho*_*que 35

数组类中的大多数方法仅适用于一维数组,因此您必须手动执行复制:

T[,] ResizeArray<T>(T[,] original, int rows, int cols)
{
    var newArray = new T[rows,cols];
    int minRows = Math.Min(rows, original.GetLength(0));
    int minCols = Math.Min(cols, original.GetLength(1));
    for(int i = 0; i < minRows; i++)
        for(int j = 0; j < minCols; j++)
           newArray[i, j] = original[i, j];
    return newArray;
}
Run Code Online (Sandbox Code Playgroud)

要理解它无法使用的原因Array.Copy,您需要考虑内存中多维数组的布局.数组项目不真正存储为二维阵列,他们一行之后连续存储,一行.所以这个数组:

{ { 1, 2, 3 },
  { 4, 5, 6 } }
Run Code Online (Sandbox Code Playgroud)

实际上是这样安排在内存中: { 1, 2, 3, 4, 5, 6 }

现在,假设您要再添加一行和一列,以便数组如下所示:

{ { 1, 2, 3, 0 },
  { 4, 5, 6, 0 },
  { 0, 0, 0, 0 } }
Run Code Online (Sandbox Code Playgroud)

内存中的布局现在如下: { 1, 2, 3, 0, 4, 5, 6, 0, 0, 0, 0, 0 }

但是Array.Copy将所有数组视为一维的.MSDN说:

在多维数组之间进行复制时,数组的行为就像一个长的一维数组,其中行(或列)在概念上是端对端放置的

因此,当您尝试将原始数组复制到新数组时,它只会将一个内存位置复制到另一个内存位置,这将以一维表示形式给出:

{ 1, 2, 3, 4, 5, 6, 0, 0, 0, 0, 0, 0 }.

如果将其转换为二维表示,则会得到以下内容:

{ { 1, 2, 3, 4 },
  { 5, 6, 0, 0 },
  { 0, 0, 0, 0 } }
Run Code Online (Sandbox Code Playgroud)

这就是为什么你得到一个搞砸的数组...注意,如果你改变行数而不是列数,它将工作属性.

  • 如果`(rows <oldRows)||(cols <oldCols)`则抛出.需要在循环中使用`Min(rows,oldRows)`. (2认同)

Ste*_*ney 13

这结合了Thomas和Manuel的答案,并提供了Array.Copy的性能优势以及增加和减小阵列大小的能力.

    protected T[,] ResizeArray<T>(T[,] original, int x, int y)
    {
        T[,] newArray = new T[x, y];
        int minX = Math.Min(original.GetLength(0), newArray.GetLength(0));
        int minY = Math.Min(original.GetLength(1), newArray.GetLength(1));

        for (int i = 0; i < minY; ++i)
            Array.Copy(original, i * original.GetLength(0), newArray, i * newArray.GetLength(0), minX);

        return newArray;
    }
Run Code Online (Sandbox Code Playgroud)

请注意,阵列的x轴和y轴取决于您自己的实现,您可能需要切换0和1以获得所需的效果.


Man*_*uel 9

谢谢Thomas,您的解释非常有用,但您实施的解决方案太慢了.我修改它以使Array.Copy得到很好的使用.

    void ResizeArray<T>(ref T[,] original, int newCoNum, int newRoNum)
    {
        var newArray = new T[newCoNum,newRoNum];
        int columnCount = original.GetLength(1);
        int columnCount2 = newRoNum;
        int columns = original.GetUpperBound(0);
        for (int co = 0; co <= columns; co++)
            Array.Copy(original, co * columnCount, newArray, co * columnCount2, columnCount);
        original = newArray;
    }
Run Code Online (Sandbox Code Playgroud)

这里我假设行数多于列数,因此我将数组结构为[columns,rows].这样我一次在整个列上使用Array.Copy(一次比一个单元快得多).

它只能增加数组的大小,但可以调整它以减小大小.