【问题标题】:matrix to array c#矩阵到数组 c#
【发布时间】:2012-02-18 08:42:09
【问题描述】:

这将是转换像这样的方阵最有效的方法

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

【问题讨论】:

  • [This][1] 似乎是相同的问题,已回答。 [1]:stackoverflow.com/questions/2569279/…
  • @Olexsi 不太一样;这个问题使用了一个适当的二维数组,而你链接到的问题是一个二维锯齿状数组。

标签: c# arrays matrix


【解决方案1】:

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

【讨论】:

  • 哪个更快更省资源?
  • 我不知道,我自己没有分析过。但我怀疑第三个版本会是最快的。
  • LINQ 是什么?我希望它会快
  • 看起来第二个实际上是最快的,第三个在大约 120 毫秒内非常接近。在我的测试中,第一个版本的速度比最快的慢 55 倍。一百万次迭代转换一个 10x10 矩阵。 time ms (ticks): 27349ms (75675449), 491ms (1359839), 614ms (1700921).
  • @JeffMercado 在第一个例子中,没有必要调用 .Cast() 因为元素已经是整数。
【解决方案2】:

正如 Jeff 所说,LINQ 使这变得微不足道。 OfType&lt;&gt;() 通常应该比 Cast&lt;&gt; 快一点:

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

OfType&lt;&gt; 的实现仍然会受到装箱/拆箱处罚,正如 @phoog 所提到的。

只是为了好玩,如果您想要一个基于 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 的内置选项获得更好的性能。然而,杰夫的第二个解决方案似乎总是禁食。

【讨论】:

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      最好一次性分配完整的结果数组,然后将数据复制进去。

      你应该找到这样的总大小;

      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's memcpy 函数来执行低级块复制。这是尽可能高效的。

      【讨论】:

        猜你喜欢
        • 2017-08-03
        • 2015-10-13
        • 2016-08-13
        • 2011-03-21
        • 1970-01-01
        • 1970-01-01
        • 2012-11-12
        • 1970-01-01
        相关资源
        最近更新 更多