2010-10-18 1 views
2

У меня возникла проблема, когда я хотел бы создать таблицу массивов. Это 2-мерный массив, в котором количество строк и столбцов известно во время выполнения до того, как таблица должна быть создана. Количество столбцов одинаково для всех строк.Как получить ссылку на одно измерение многомерного массива в C#?

После создания массива я хотел бы работать только с одним размером этого массива. Возможно, передайте ссылку на метод.

Вот вымышленный пример:

// Create a table 3x3 table. 
int[,] DistanceTable = new int[3, 3]; 
DistanceTable[0, 0] = 0; 
DistanceTable[1, 1] = 0; 
DistanceTable[2, 2] = 0; 

DistanceTable[0, 1] = 10; 
DistanceTable[0, 2] = 40; 

DistanceTable[1, 0] = 10; 
DistanceTable[1, 2] = 25; 

DistanceTable[2, 0] = 40; 
DistanceTable[2, 1] = 25; 

// Why can't I do this? 
int[] twos = DistanceTable[2]; 

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

Возможно ли это? Если не так?

Thanks

+0

Вам нужен зубчатый массив. Не проходите мимо, не собирайте 200 долларов без них. –

ответ

3

Нет. Многомерные массивы отличаются от массивов Jagged тем, что они сохраняются последовательно в одном блоке памяти с использованием Row-Major ordering.

Из-за этого вытаскивание одной «колонки» данных требует пропуска, чтобы вытащить это.

Жесткие массивы, с другой стороны, представляют собой массив ссылок на второй массив. Это позволяет легко вытащить отдельные «массивы» из зубчатого массива.

Но мне не нужен JaggedArray, потому что мой многосегментный массив всегда имеет одинаковое количество столбцов для каждой строки.

Измельченные массивы в .NET имеют огромную оптимизацию производительности. Они часто превосходят многомерные массивы. Вот почему большинство процедур анализа кода предполагают преобразование в неровный массив из двухмерного массива. Было бы целесообразно рассмотреть это, даже если вам это не нужно.

+0

Интересно. Я бы подумал, что многомерные массивы будут более эффективными (отсюда и мое желание использовать их). Спасибо за отличное объяснение! Жесткий массив! – Justin

+0

@ Justin: Да, это очень противоречиво. –

+0

@ Justin: Jagged обычно быстрее - но ** делает ** использовать больше памяти. –

2

Это невозможно; многомерные массивы не работают так.

В общем, вы всегда должны использовать зубчатые массивы; они быстрее.
(джиттер будет генерировать инструкции сырых памятей доступа вместо вызовов методов)

+2

Почему JITTER не делает это для многомерных массивов? –

1

Существует только один объект массива с многомерным массивом в то время как зубчатый массивом является вложенностью нескольких различных объектов массива. Не существует 1-1 сопоставления или метода извлечения (который не включает использование обертки).

0

Вы можете сделать метод расширения на свой объект DictionaryTable, который позволяет указать строку?

public static class IntArrayExt 
{ 
    public static int[] Row(this int[,] array, int row) 
    { 
     int[] newArray = new int[3]; 
     for (int i = 0; i < array.Length; i++) 
     { 
      newArray[i] = array[row, i]; 
     } 
     return newArray; 
    } 
} 

int[,] distanceTable = new int[3, 3]; 
distanceTable[0, 0] = 0; 
distanceTable[1, 1] = 0; 
distanceTable[2, 2] = 0; 

distanceTable[0, 1] = 10; 
distanceTable[0, 2] = 40; 

distanceTable[1, 0] = 10; 
distanceTable[1, 2] = 25; 

distanceTable[2, 0] = 40; 
distanceTable[2, 1] = 25; 

int[] twos = distanceTable.Row(2); 

Вы можете сделать другой метод расширения, если хотите получить столбец.

1

Извините, это должен быть комментарий к How do I get a reference to a single dimension of a Multidemensional Array in C#?, но я еще не могу прокомментировать ..

Во всяком случае, причина, почему производительность лучше с зубчатым массива легко понять через какое-то объяснение: Давайте рассмотрим многомерный массив:

{{0, 1, 2}, {3, 4 , 5}, {6, 7, 8}}

В памяти хранится что-то вроде этого: {0, 1, 2, 3, 4, 5, 6, 7, 8}.

Теперь предположим, что вы хотите получить доступ к [0, 0], где в памяти мы будем читать? Нам нужно вычислить адрес: y * 3 + x => 0 * 3 + 0 => 0. После этого мы можем продолжить и выполнить фактическое чтение. В случае, если мы хотим прочитать всю строку, мы должны повторять эту математику снова и снова.

Вместо этого смотреть на зубчатым массив, в памяти он хранится что-то вроде этого:

а: {0, 1, 2} б: {3, 4, 5} C: {6, 7 , 8} {ref: a, ref: b, ref: c}

Предположим, мы хотим получить доступ к [0] [0], где в памяти мы будем читать? Сначала дадим ссылку на массив [0]. А затем получите содержимое ячейки [0]. Готово. Если мы хотим прочитать всю строку, нам нужно только увеличить указатель на единицу.

Если мы собираемся перебирать весь массив, а не только одну строку, это все равно то же преимущество производительности для зубчатых массивов.

Есть одно исключение: итерация столбцов. Это очень плохо для зубчатых массивов, так как мы собираемся сделать относительную дорогостоящую память для каждого доступа. Нехорошо.

Если вы чувствуете, что это проблема, остается один метод: одномерный массив! В этом случае мы используем теорию за многомерным массивом (y * rowLength + x) и используем некоторую действительно простую математику; Для итерации строки: просто увеличивайте на единицу, чтобы итерации столбца: просто увеличивайте на rowLength.

+0

Расчетное смещение кажется тривиальным (и, конечно же, не более дорогим, чем косвенный поиск?); Я подозреваю, что улучшенные улучшения производительности связаны с лучшими кэшированием, конкретными примерами оптимизации и шаблонами использования, которые также могут быть связаны с тем, как два подхода «вытягивают» общие шаблоны итераций. И добро пожаловать в SO :-) – 2010-10-19 03:03:26

+0

В большинстве приложений тривиально, однако, когда вы выполняете итерацию больших массивов и не выполняете многого, там есть производительность. Но, конечно, не переусердствуйте .. :) И спасибо :) – Onkelborg

 Смежные вопросы

  • Нет связанных вопросов^_^