Array.Copy是否适用于多维数组?

33

这段代码运行正常:

var newArray = new Rectangle[newHeight, newWidth];

for (int x = 0; x < newWidth; x++)
    for (int y = 0; y < newHeight; y++)
        newArray[y, x] = (x >= width) || (y >= height) ? Rectangle.Empty : tiles[y, x];

但我用 Array.Copy 尝试替换它并不太成功。如果调整大小后的数组更大,它会在边缘添加空白矩形。如果它更小,则应该只裁剪掉边缘。

当执行以下代码:

Array.Copy(tiles, newArray, newWidth * newHeight);

它会弄乱数组,并且其中所有内容都变得无序,不保留原始索引。也许我脑子里有点混乱或者别的什么问题?

4个回答

50

是的,但是它不是按照你想象的方式工作。相反,它将每个多维数组视为单个维度数组(实际上它们在内存中就是这样的,这只是一个技巧,让我们在上面放置一些结构来将它们视为多维),然后复制这些单维度结构。所以如果你有:

1 2 3
4 5 6

并想将它复制到

x x x x
x x x x

那么它将把第一个数组看作

1 2 3 4 5 6

和第二个作为

x x x x x x x x

结果将会是:

1 2 3 4 5 6 x x

这会以某种方式呈现给您

1 2 3 4
5 6 x x

明白了吗?


1
哇,谢谢。我终于懂得如何使用它了。一直以来,我从未想过它可以用于多维数组。 - Martheen
我理解,但有没有办法修复它,使其正常工作? - Andrew Godfrey
1
我完全支持代码重用,但是你想要替换已经工作的三行代码有具体的原因吗? - Paul Walls
@Andrew Godfrey:它正在正常工作;只是它不是按照你认为应该工作的方式工作。没有办法让它按照你认为应该工作的方式工作。Array.Copy旨在快速复制,这意味着利用线性连续内存块复制的事实非常快。你要求以非线性连续的方式进行复制。Array.Copy并不适合这项工作。你必须找到其他可以为你完成这项工作的东西。特别是,你已经编写的代码完全符合你的要求。使用它。 - jason
好的,谢谢!我只是在想,因为我的程序已经完成了,现在我只是在重构它,让它看起来漂亮O_O。 - Andrew Godfrey
4
请记住,尽管 Array.Copy 不要求源数组和目标数组在每个维度上的长度相同,但它要求两者具有相同的秩(维数)。Buffer.BlockCopy 没有这个限制。 - rwong

6
我使用这段代码:
public static void ResizeBidimArrayWithElements<T>(ref T[,] original, int rows, int cols)
{

    T[,] newArray = new T[rows, cols];
    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 < minX; ++i)
        Array.Copy(original, i * original.GetLength(1), newArray, i * newArray.GetLength(1), minY);

    original = newArray;

}

这样调用字符串数组

ResizeBidimArrayWithElements<string>(ref arrayOrigin, vNumRows, vNumCols);

4

只需使用以下方式的"Clone()"函数:

这是您的数组列表

object newArray = new object [row, column];

当您创建另一个数组时,请使用以下代码:

当您创建另一个数组时,请使用以下代码:

object[,] clonedArray = (object[,]) newArray.Clone();

简单!玩得开心!


3
我认为这不正确,因为Clone()只会创建一个新指针,指向旧数组的当前内存。这意味着如果您在新数组中进行任何更改,它将被应用回原始数组。 - dalmate

3

我需要从一个缓冲区中读取数据并复制到一个大的保存数组中,以便在下一个中断到达之前完成。使用循环进行复制不是一个选项,速度太慢了。在所有复制完成之前,我不需要组合数据的多维结构,这意味着我可以使用Buffer.BlockCopy()将数据复制到单维数组中,然后再次复制到多维数组中以获取所需的结构。以下是一些代码(在控制台中运行),展示了这种技术以及其性能。

static class Program
{
    [STAThread]
    static void Main()
    {
        Stopwatch watch = new Stopwatch();

        const int width = 2;
        const int depth = 10 * 1000000;

        //  Create a large array of data
        Random r = new Random(100);
        int[,] data = new int[width, depth];
        for(int i = 0; i < width; i++)
        {
            for(int j = 0; j < depth; j++)
            {
                data[i, j] = r.Next();
            }
        }

        //  Block copy to a single dimension array
        watch.Start();
        int[] buffer = new int[width * depth];
        Buffer.BlockCopy(data, 0, buffer, 0, data.Length * sizeof(int));
        watch.Stop();
        Console.WriteLine("BlockCopy to flat array took {0}", watch.ElapsedMilliseconds);

        //  Block copy to multidimensional array
        int[,] data2 = new int[width, depth];
        watch.Start();
        Buffer.BlockCopy(buffer, 0, data2, 0,buffer.Length * sizeof(int));
        watch.Stop();
        Console.WriteLine("BlockCopy to 2 dimensional array took {0}", watch.ElapsedMilliseconds);


        //  Now try a loop based copy - eck!
        data2 = new int[width, depth];
        watch.Start();
        for (int i = 0; i < width; i++)
        {
            for (int j = 0; j < depth; j++)
            {
                data2[i, j] = data[i, j];
            }
        }
        watch.Stop();
        Console.WriteLine("Loop-copy to 2 dimensional array took {0} ms", watch.ElapsedMilliseconds);
    }
}

输出:

BlockCopy to flat array took 14 ms
BlockCopy to 2 dimensional array took 28 ms
Loop-copy to 2 dimensional array took 149 ms

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接