Как скопировать строку значений из двумерного массива в одномерный массив? - PullRequest
15 голосов
/ 28 апреля 2009

У нас есть следующий объект

int [,] oGridCells;

, который используется только с фиксированным первым индексом

int iIndex = 5;
for (int iLoop = 0; iLoop < iUpperBound; iLoop++)
{
  //Get the value from the 2D array
  iValue = oGridCells[iIndex, iLoop];

  //Do something with iValue
}

Есть ли в .NET способ преобразовать значения с фиксированным первым индексом в один массив измерений (кроме как путем зацикливания значений)?

Я сомневаюсь, что это ускорит код (и может замедлить его), если массив будет зациклен только один раз. Но если с массивом сильно манипулируют, то одномерный массив будет более эффективным, чем многомерный массив.

Моя основная причина задать вопрос - посмотреть, можно ли это сделать и как, а не использовать его для производственного кода.

Ответы [ 6 ]

29 голосов
/ 28 апреля 2009

Следующий код демонстрирует копирование 16 байтов (4 дюймов) из двумерного массива в одномерный массив.

int[,] oGridCells = {{1, 2}, {3, 4}};
int[] oResult = new int[4];
System.Buffer.BlockCopy(oGridCells, 0, oResult, 0, 16);

Вы также можете выборочно скопировать только 1 строку из массива, указав правильные смещения байтов. В этом примере копируется средняя строка 3-рядного двумерного массива.

int[,] oGridCells = {{1, 2}, {3, 4}, {5, 6}};
int[] oResult = new int[2];
System.Buffer.BlockCopy(oGridCells, 8, oResult, 0, 8);
2 голосов
/ 28 апреля 2009

Edit:

Я понял, что есть способ! Конечно, это того не стоит. Используйте небезопасный код . Полный пример, показывающий оба пути, с небезопасным ниже:

public class MultiSingleUnsafe
{
    public static unsafe void Main(String[] a)
    {
    int rowCount = 6;
    int iUpperBound = 10;
    int [,] oGridCells = new int[rowCount, iUpperBound];

    int iIndex = rowCount - 2; // Pick a row.

    for(int i = 0; i < iUpperBound; i++)
    {
        oGridCells[iIndex, i] = i;
    }

    for (int iLoop = 0; iLoop < iUpperBound; iLoop++)
    {
        //Get the value from the 2D array
        int iValue = oGridCells[iIndex, iLoop];
        Console.WriteLine("Multi-dim array access iValue: " + iValue);
        //Do something with iValue
    }

    fixed(int *lastRow = &(oGridCells[iIndex,0]))
    {   
        for (int iLoop = 0; iLoop < iUpperBound; iLoop++)
        {
        int iValue = lastRow[iLoop];
        Console.WriteLine("Pointer access iValue: " + iValue);
        }
    }
    }
}

Я не знаю, как преобразовать многомерный массив в одномерный в C #. Конечно, вы можете создать новый одномерный массив и скопировать в него. Но я не думаю, что это даст выигрыш в производительности, даже если вы перебираете значения несколько раз. Как сказала Дарен, внутренне это все равно арифметика указателей. Если вы хотите быть уверенным, профилируйте это.

1 голос
/ 18 августа 2017

Вы можете попробовать это:

 int[,] twoD = new int[2,2];
 twoD[0, 0] = 1;
 twoD[0, 1] = 2;
 twoD[1, 0] = 3;
 twoD[1, 1] = 4;

 int[] result = twoD.Cast<int>().Select(c => c).ToArray();

Результатом будет целочисленный массив с данными:

1, 2, 3, 4
1 голос
/ 28 апреля 2009

"Но если бы массивом манипулировали, то массив с одним измерением был бы более эффективным, чем массив с несколькими измерениями."

Я провел некоторое профилирование именно этим летом и был удивлен, что не увидел существенного различия в производительности между массивами 2D и 1D.

Я не тестировал производительность зубчатого массива.

1 голос
/ 28 апреля 2009

Вы не можете получить ссылку на каждый массив. Однако вы можете использовать зубчатый массив .

0 голосов
/ 28 апреля 2009

Я был бы удивлен, если бы это было возможно: я держу пари, что oGridCells[iIndex, iLoop] - это просто своего рода сокращение (внутренне в MSIL) для oGridCells[iIndex * iLoop], и что многомерные массивы являются синтаксическим сахаром для этого.

Чтобы ответить на ваш вопрос: Нет. Вам придется зацикливать значения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...