【问题标题】:Does Array.Copy work with multidimensional arrays?Array.Copy 是否适用于多维数组?
【发布时间】:2011-11-08 02:17:52
【问题描述】:

这段代码运行良好:

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);

它弄乱了数组,它的所有内容都变得无序并且不保留它们的原始索引。也许我只是在胡思乱想之类的?

【问题讨论】:

    标签: c# arrays multidimensional-array


    【解决方案1】:

    是的。但是,它并不像您认为的那样起作用。相反,它将每个多维数组视为一个单维数组(这实际上是它们在内存中的样子,这只是一个技巧,让我们可以在它们之上放置一些结构以将它们视为多维),然后复制单个维结构。所以如果你有

    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
    

    知道了吗?

    【讨论】:

    • 哇,谢谢。我终于知道如何使用它了。一直以来,我从没想过它会适用于多维数组
    • 我明白了,但是有什么办法可以修复它以使其正常工作吗?
    • 我完全赞成代码重用,但是您是否有特定原因要替换您的工作 3 行代码?
    • @Andrew Godfrey:它工作正常;它只是没有按照您认为应该工作的方式工作。没有办法让它以您认为应该工作的方式工作。 Array.Copy 意味着速度极快,这意味着利用复制线性连续内存块速度极快的事实。您要求以非线性连续的方式进行复制。 Array.Copy 不适合这份工作。你必须找到其他可以为你做这件事的东西。特别是,您已经编写的代码完全符合您的要求。使用它。
    • 请记住,尽管Array.Copy 不要求其源数组和目标数组在每个维度上的长度相同,但它确实要求两者具有相同的Rank (维数)。 Buffer.BlockCopy 没有这个限制。
    【解决方案2】:

    我使用这个代码:

    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);
    

    【讨论】:

      【解决方案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
      

      【讨论】:

        【解决方案4】:

        简单地使用“Clone()”函数,如下所示:

        这是你的数组列表

        object newArray = new object [row, column];
        

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

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

        简单!玩得开心!

        【讨论】:

        • 我认为这是不正确的,因为 Clone() 只会创建一个指向旧数组当前内存的新指针。这意味着如果您更改新数组中的任何内容,它将被应用回原始数组。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-08
        • 1970-01-01
        • 1970-01-01
        • 2023-03-13
        • 1970-01-01
        相关资源
        最近更新 更多