Массивы в C#. Многомерные массивы - C# и .NET

Массивы в C#. Многомерные массивы

В предыдущей части мы рассмотрели самый простой и, по-видимому, самый широко используемый вид массивов – одномерные массивы. Вместе с тем, язык C# позволяет создавать массивы с самым различным количеством измерений. Такие массивы называются многомерными. Многомерные массивы – это массивы, содержащие два и более измерений. В этой части мы, в основном, сосредоточим свое внимание на двумерных массивах.

Многомерные массивы в C#

Визуализация многомерного массива

Двумерный массив можно представить как матрицу элементов:

Многомерные массивы

В таком массиве доступ к каждому элементу можно получить, используя дву индекса – индекс строки и индекс столбца. Нетрудно себе представить и трехмерный массив – это куб элементов и доступ к каждому элементу мы можем получить по трем индексам (для каждого измерения – свой индекс). С прочими многомерными массивами по-сложнее. Уже на четырехмерном массиве становится трудно представить себе визуально, что из себя представляет массив, но и сами по себе, такие массивы используются в практике не часто. Обычно нам хватает одномерных и двумерных массивов.

Как создать многомерный массив в C#

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

int[,] numbersMatrix; //двумерный массив
int[,,] numbersCube; //трехмерный массив

Обратите внимание на запятые, которые ставятся в квадратных скобках рядом с типом элементов массива. То есть, визуально, количество измерений массива можно определить по количеству этих самых запятых: одна запятая – двумерный массив, две запятых – трехмерный и так далее.

Способы инициализации многомерных массивов представим на примере двумерного массива:

int[,] array = { { 0, 1 },
                 { 2, 3 },
                 { 4, 5 },
                 { 6, 7 },
                 { 8, 9 }
                };

int[,] array2 = new[,] { { 0, 1 },
                         { 2, 3 },
                         { 4, 5 },
                         { 6, 7 },
                         { 8, 9 }
                       };

В обоих случаях мы создаем массив на 10 элементов. Чтобы получить значение элемента массива мы теперь должны использовать индекс строки и индекс столбца. Например,

Console.WriteLine(array[3, 1]); //вернет значение 7

Свойства и методы многомерных массивов

Свойства и методы многомерных массивов точно такие же, как и одномерных. И здесь мы уже можем рассмотреть применение этих свойств на практике. Например,

int[,] array = { { 0, 1 },
                 { 2, 3 },
                 { 4, 5 },
                 { 6, 7 },
                 { 8, 9 }
                };

Console.WriteLine($"Количество измерений в массиве {array.Rank}");
Console.WriteLine($"Общее количество элементов в массиве {array.Length}");
for (int i = 0; i < array.Rank; i++)
{
    Console.WriteLine($"Количество элементов в {i+1}-м измерении {array.GetUpperBound(i)+1}");
}

Метод GetUpperBound()возвращает значение индекса последнего элемента в заданном измерении массива (верхнюю границу). Поэтому, чтобы получить количество элементов в измерении мы прибавляем к полученному значению 1. Что касается свойства Rank, то здесь действует то же правило, что и для индексов элементов массива, то есть первое измерение имеет значение 0, второе – 1 и так далее. Результат выполнения этого кода будет следующим:

Многомерные массивы

Перебор элементов многомерного массива C#

В цикле foreach

Цикл foreach предоставляет нам самый простой и понятный способ доступа к каждому элементы массива. Например, возьмем наш двумерный массив и попробуем перебрать все его элементы в цикле foreach:

foreach (int i in array)
{
    Console.Write("{0} ", i);
}

В результате, в консоли появится строка, содержащая элементы массива:  0 1 2 3 4 5 6 7 8 9

Цикл foreach «разворачивает» массив в строку, наращивая вначале индексы самого правого измерения (в нашем случае, это измерение имеет длину 2), а затем смещается влево и перебирает все индексы этого измерения

Это очень простой способ добраться до всех элементов многомерного массива. Но, что делать, если нам необходимо пройти только по крайнему правому столбцу? То есть получить значения 1, 3, 5, 7, 9. Для этого мы можем воспользоваться циклом for.

В цикле for

Цикл for даёт более гибкий механизм работы с массивами C#. Итак, получим все значения элементов из последнего столбца. Вариантов множество, но мы рассмотрим два из них. Первый вариант можно использовать, когда ранг массива известен и мы знаем размерность (количество элементов) последнего измерения:

for (int i = 0; i < array.GetLength(0); i++)
    Console.Write("{0} ", array[i,1]);

здесь в условии цикла мы воспользовались методом GetLength(), чтобы получить количество элементов по первому измерению (5), а уже в теле цикла получаем значения элементов в каждой строке во втором столбце (помним, что индекс первых элементов в массиве всегда равен 0).

Второй вариант используется, когда мы не знаем размерность второго измерения. Исходный код “развернут” для понимания (добавлены некоторые переменные, раскрывающие смысл работы):

int rank = array.Rank-1;
int maxIndex = array.GetUpperBound(0) + 1;

for (int i=0; i<maxIndex; i++)
   Console.Write("{0} ", array[i, array.GetUpperBound(rank)]);

В цикле  мы запрашиваем элемент с индексами:

array[i, //текущая строка
array.GetUpperBound(rank)]) //последний столбец

Соответственно, если необходимо пройти по всем элементам массива, то можно использовать вложенные циклы for и организовать доступ к элементам массива в любом порядке — построчно, по столбцам, хоть по диагонали — решение зависит от поставленной задачи.

Поведем итог

Язык C# поддерживает создание многомерных массивов. При этом, количество измерений может быть каким угодно, однако, наиболее часто среди многомерных массивов в C# используются двумерные и трехмерные массивы. Для перебора элементов многомерного массива мы также можем использовать циклы. При этом, цикл foreach“разворачивает” массив, получая доступ к каждому элементу массива по очереди.

Домашнее задание №21

Дан двумерный массив целых m на n элементов. Заполнить массив случайными числами, вывести массив в консоль и определить максимальное и минимальное значение в каждой строке массива. Для получения случайного числа использовать выражение Random.Shared.Next()