矩阵到数组c#

本文关键字:数组 | 更新日期: 2023-09-27 18:21:16

转换这样的平方矩阵的最有效方法

  1 2 3 
  4 5 6
  7 8 9 

进入

[1 2 3 4 5 6 7 8 9]

在c#中

我在做

int[,] array2D = new int[,] { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
int[] array1D = new int[9];
int ci=0;
 for (int i = 0; i < 3; i++)
 {
      for (int j = 0; j < 3; j++)
      {
            array1D[ci++] = array2D[i, j]);
      }
 }

矩阵到数组c#

LINQ使这变得微不足道。

int[,] array2d = ...;
var array1d = array2d.Cast<int>().ToArray();

否则,你的方法是足够的,但可以推广:

int[,] array2d = ...;
var rows = array2d.GetLength(0);
var cols = array2d.GetLength(1);
var array1d = new int[rows * cols];
var current = 0;
for (int i = 0; i < rows; i++)
{
    for (int j = 0; j < cols; j++)
    {
        array1d[current++] = array2d[i, j];
    }
}

甚至:

int[,] array2d = ...;
var array1d = new int[array2d.GetLength(0) * array2d.GetLength(1)];
var current = 0;
foreach (var value in array2d)
{
    array1d[current++] = value;
}

正如Jeff所说,LINQ让这件事变得微不足道。OfType<>()通常应该比Cast<>快一点,不过:

array1D = array2D.OfType<int>().ToArray();

然而,正如@phoog所提到的,OfType<>的实现仍将受到装箱/取消装箱处罚。

只是为了好玩,如果你想要一个快速的基于LINQ的解决方案(避免装箱的成本),你可以使用这个小的扩展方法:

static class LinqEx
{
    public static IEnumerable<T> Flatten<T>(this T[,] matrix)
    {
        foreach (var item in matrix) yield return item;
    }
}

或者这个,基于Jeff的第二个解决方案:

    public static IEnumerable<T> Flatten<T>(this T[,] matrix)
    {
        var rows = matrix.GetLength(0);
        var cols = matrix.GetLength(1);
        for (var i = 0; i < rows;i++ )
        {
            for (var j = 0; j < cols; j++ )
                yield return matrix[i, j];
        }
    }

用法:

 int[,] array2D = new int[,] { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };  
 int[] array1D = array2D.Flatten().ToArray();

我没有完全介绍这一点,但我希望这将比基于LINQ/IEnumerable的内置选项获得更好的性能。然而,杰夫的第二个解决方案似乎总是禁食。

使用Buffer.BlockCopy:的替代解决方案

int[,] array2D = new int[,] { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
int[] array1D = new int[ array2D.Length ];
Buffer.BlockCopy(array2D, 0, array1D, 0, array1D.Length * sizeof(int));

您最好一次性分配完整的结果数组,然后将数据复制到.中

你应该找到这样的总尺寸;

var size = arrays.Sum(a=> a.Length);
var result = new int[size];

然后使用Array.CopyTo复制数组,而不是循环自己;

var cursor = 0;
foreach(var a in arrays) {
   a.CopyTo(result, cursor);
   cursor += a.Length;    
}

Array.CopyTo将比您自己的循环更快;至少,不是更慢。它可能会在内部使用C的memcpy函数来进行低级别的块复制。这是尽可能高效的。