【问题标题】:How to copy one-dimensional array into two-dimensional [duplicate]如何将一维数组复制成二维[重复]
【发布时间】:2021-10-18 11:00:27
【问题描述】:

具备以下条件:

        int[,] a = new int[4, 2];
        int[] b = new int[2];

如何将 b 中的值复制到 a 的第一个元素中? b.CopyTo(a[0]) 怎么了?

【问题讨论】:

标签: c#


【解决方案1】:

您只能使用 2 个坐标(所以 a[x,y])访问 a,因为它是使用 2 个维度定义的。

尝试改用int[][] a,如果你这样做了,那么a会变成一个包含一维子数组的数组,然后你可以使用1个坐标来访问子数组。

示例代码:

int[][] a = new int[4][];
a[0] = new int[2];
int[] b = new int[2];

请注意,在此之后,当我尝试对 b.CopyTo(a[0]) 执行操作时,我收到“调用不明确”编译错误(在 .NET 5 中),因为有两种不同的扩展方法都匹配 CopyTo 签名...

【讨论】:

【解决方案2】:

b.CopyTo(a[0]) 有什么问题?

A 是一个二维数组,所以需要两个索引,即a[0,0] = b[0]

我建议不要使用内置的多维数组,而是使用围绕一维数组的包装器,使用类似这样的索引器:

public T this[int x, int y]
{
    get => Data[y * Width + x];
    set => Data[y * Width + x] = value;
}

这具有更易于互操作性的优点,因为许多系统将各种类型的 2D 缓冲区公开为 1D 数据 + 大小。这允许通过块复制而不是逐个元素复制数据来完成复制数据。

【讨论】:

    【解决方案3】:

    对于原始数组类型,您可以使用 Buffer.BlockCopy(); 定义用于打包或解包数组的扩展方法

    static class Program
    {
        static void Main(string[] args)
        {
            int[,] A = new[,] { { 1, 2 }, { 3, 4 } };
            int[] data = A.PackMarix();
            int[,] B = data.UnPackMarix(2, 2);
    
            Console.WriteLine(B);
        }
    
        public static int[,] UnPackMarix(this int[] data, int rows, int columns)
        {
            int[,] result = new int[rows, columns];
            int bytes = Buffer.ByteLength(data);
            Buffer.BlockCopy(data, 0, result, 0, bytes);
            return result;
        }
        public static int[] PackMarix(this int[,] data)
        {
            int[] result = new int[data.Length];
            int bytes = Buffer.ByteLength(data);
            Buffer.BlockCopy(data, 0, result, 0, bytes);
            return result;
        }
    }
    

    对于非原始类型,您必须手动进行复制

        public static T[,] UnPackMarix<T>(this T[] data, int rows, int columns) 
        {
            var result = new T[rows, columns];
            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < columns; j++)
                {
                    result[i, j] = data[i * columns + j];
                }
            }
            return result;
        }
        public unsafe static T[] PackMarix<T>(this T[,] data)
        {
            var result = new T[data.Length];
            int rows = data.GetLength(0);
            int columns = data.GetLength(1);
            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < columns; j++)
                {
                    result[i * columns + j] = data[i, j];
                }
            }
            return result;
        }
    

    【讨论】:

      【解决方案4】:

      这之前已经在 SO 上发布过,但我找不到旧帖子。无论如何,请使用 Microsoft High Performance toolkit。它具有二维内存的跨度。有了它,你可以这样做:

              int[,] a = new int[4, 2];
      
              int[] b = { 1, 2 };
      
              var spanB = b.AsSpan();
              var spanA = a.AsSpan2D();
      
              spanB.CopyTo(spanA.GetRowSpan(0));
      
              foreach (var i in spanA)
                  Console.WriteLine(i);
      

      【讨论】:

        猜你喜欢
        • 2020-07-06
        • 1970-01-01
        • 1970-01-01
        • 2021-12-31
        • 2019-04-28
        • 2023-04-11
        • 2010-11-29
        • 2014-04-23
        • 2018-02-09
        相关资源
        最近更新 更多