матрица для массива c # - PullRequest
       10

матрица для массива c #

3 голосов
/ 25 января 2012

Какой самый эффективный способ преобразовать квадратную матрицу, такую ​​как

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

Ответы [ 4 ]

7 голосов
/ 25 января 2012

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;
}
1 голос
/ 19 сентября 2017

Альтернативное решение с использованием 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));
1 голос
/ 25 января 2012

Как сказал Джефф, LINQ делает это тривиальным. OfType<>() обычно должно быть немного быстрее, чем Cast<>, хотя:

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

Однако реализация OfType<> все равно будет страдать от штрафов за бокс / распаковку, как упоминал @phoog.

Просто для удовольствия, если вы хотите быстрое решение на основе LINQ (избегая затрат на бокс), вы можете использовать этот небольшой метод расширения:

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

Или это, основываясь на втором решении Джеффа:

    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. Второе решение Джеффа, однако, всегда будет натощак.

0 голосов
/ 13 июля 2016

Вам всегда лучше выделить весь массив результатов одним ударом, а затем скопировать данные.

Вы должны найти общий размер, как этот;

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 для создания низкоуровневой блочной копии. Это настолько эффективно, насколько это возможно.

...