Перейти до основного вмісту

Масиви

Масив являє собою набір даних одного типу. Оголошення масиву подібне до оголошення змінної, за винятком того, що після типу ставляться квадратні дужки:

тип_змінної[] ім'я_масиву;

Наприклад, оголосимо масив цілих чисел:

числа типу int[];

Після визначення змінної масиву ми можемо присвоїти їй конкретне значення:

int[] nums = new int[4];

Тут спочатку оголошено масив nums, який буде зберігати дані типу int. Потім з допомогою операції new ми виділили пам'ять для 4 елементів масиву: new int[4]. Число 4 також називається довжиною масиву. При такому визначенні всі елементи отримують значення за замовчуванням, яке передбачено для їх типу. Для типу int значенням за замовчуванням є 0.

Ми також можемо одразу вказати значення для цих елементів:

int[] nums2 = new int[4] { 1, 2, 3, 5 };

int[] nums3 = new int[] { 1, 2, 3, 5 };

int[] nums4 = new[] { 1, 2, 3, 5 };

int[] nums5 = { 1, 2, 3, 5 };

Усі вищенаведені методи будуть еквівалентні.

Аналогічно можна визначати масиви інших типів, наприклад, масив значень типу string:

string[] people = { «Tom», «Sam», «Bob» };

Починаючи з C# 12, для визначення масивів можна використовувати вирази колекцій, які передбачають взяття елементів масиву в квадратні дужки:

int[] nums1 = [ 1, 2, 3, 5 ];
int[] nums2 = []; // пустий масив

Індекси та пошук елементів масиву

Для посилання на елементи масиву використовуються індекси.Індекс являє собою номер елемента в масиві, нумерація починається з нуля, тому індекс першого елемента буде 0, індекс четвертого елемента буде 3.

Використовуючи індекси, ми можемо отримати елементи масиву:

int[] numbers = { 1, 2, 3, 5 };

// отримати елемент масиву
Console.WriteLine(numbers[3]); // 5

// отримання елементу масиву в зміннуvar n = numbers[1]; // 2Console.WriteLine(n); // 2

Також можна змінювати елемент масиву за індексом:

int[] numbers = { 1, 2, 3, 5 };

// змінити другий елемент масивуnumbers[1] = 505;

Console.WriteLine(numbers[1]); // 505

А оскільки у нас масив визначений лише для 4 елементів, то ми не можемо звернутись, наприклад, до шостого елементу.Якщо ми спробуємо це зробити, то отримаємо помилку під час виконання:

int[] numbers = { 1, 2, 3, 5 };Console.WriteLine(numbers[6]); // ! Помилка - в масиві всього 4 елементи

Властивість Length та довжина масиву

Кожен масив має властивість Length, яка зберігає довжину масиву. Наприклад, нехай потрібно отримати довжину масиву чисел, створеного вище:

int[] numbers = { 1, 2, 3, 5 };

Console.WriteLine(numbers.Length); // 4

Щоб отримати довжину масиву, після імені масиву через крапку вказується властивість Length: numbers.Length.

Отримання елементів з кінця масиву

Завдяки наявності властивості Length ми можемо обчислити індекс останнього елементу масиву - це довжина масиву - 1. Наприклад, якщо довжина масиву дорівнює 4 (тобто масив має 4 елементи), то індекс останнього елементу буде 3. І, використовуючи властивість Length, ми можемо легко отримати елементи з кінця масиву:

int[] numbers = { 1, 2, 3, 5};

Console.WriteLine(numbers[numbers.Length - 1]); // 5 - перший з кінця або останній елемент
Console.WriteLine(numbers[numbers.Length - 2]); // 3 - другий з кінця або передостанній елемент
Console.WriteLine(numbers[numbers.Length - 3]); // 2 - третій елемент з кінця.

Однак, при такому підході, вирази типу numbers.Length - 1, сенс яких полягає в отриманні певного елементу з кінця масиву, роблять код важчим. Тому, починаючи з версії C# 8.0, у мові з'явився спеціальний оператор ^, за допомогою якого можна задавати індекс відносно кінця колекції.

Перепишемо попередній приклад з використанням оператора ^:

int[] numbers = { 1, 2, 3, 5};

Console.WriteLine(numbers[^1]); // 5 - перший з кінця або останній елемент
Console.WriteLine(numbers[^2]); // 3 - другий з кінця або передостанній елемент
Console.WriteLine(numbers[^3]); // 2 - третій елемент з кінця

Перерахування масивів

Для перебору масивів можна використовувати різні типи циклів. Наприклад, цикл foreach:

int[] numbers = { 1, 2, 3, 4, 5 };
foreach (int i in numbers)
{
Console.WriteLine(i);
}

Тут ми маємо масив даних типу int в якості контейнера. Тому, оголошуємо змінну з типом int

Аналогічні дії можна виконати з допомогою циклу for:

int[] numbers = { 1, 2, 3, 4, 5 };
for (int i = 0; i < numbers.Length; i++)
{
Console.WriteLine(numbers[i]);
}

У той же час, цикл for є більш гнучким у порівнянні з foreach. В той час як foreach отримує елементи контейнера послідовно і доступний тільки для читання, в циклі for ми можемо переходити на кілька елементів вперед в залежності від приросту лічильника, а також можемо модифікувати елементи:

int[] numbers = { 1, 2, 3, 4, 5 };
for (int i = 0; i < numbers.Length; i++)
{
numbers[i] = numbers[i] * 2;
Console.WriteLine(numbers[i]);
}

Ви також можете використовувати інші види циклів, наприклад, while:

int[] numbers = { 1, 2, 3, 4, 5 };
int i = 0
while(i < numbers.Length)
{
Console.WriteLine(numbers[i]);
i++;
}

Багатовимірні масиви

Масиви характеризуються таким поняттям як ранг або кількість вимірів. Вище ми розглядали масиви, які мають один вимір (тобто їх ранг дорівнює 1) - такі масиви можна представити у вигляді елемента рядка (рядка або стовпця). Але масиви можуть бути і багатовимірними. Такі масиви мають кількість вимірів (тобто ранг) більше 1.

Масиви, які мають два виміри (ранг дорівнює 2), називаються двовимірними. Наприклад, створимо одновимірний та двовимірний масиви, які мають однакові елементи:

int[] nums1 = new int[] { 0, 1, 2, 3, 4, 5 };

int[,] nums2 = { { { 0, 1, 2 }, { 3, 4, 5 } } };

Візуально обидва масиви можна представити наступним чином:

Одновимірний масив nums1

| 0 | 1 | 2 | 3 | 4 | 5 |

Двовимірний масив nums2

| 0 | 1 | 2 |
| 3 | 4 | 5 |

Оскільки масив nums2 двовимірний, він є простою таблицею. Усі можливі способи визначення двовимірних масивів:

int[,] nums1;
int[,] nums2 = new int[2, 3];
int[,] nums3 = new int[2, 3] { { { 0, 1, 2 }, { 3, 4, 5 } } };
int[,] nums4 = new int[,] { { 0, 1, 2 }, { 3, 4, 5 } } };
int[,] nums5 = new [,]{ { 0, 1, 2 }, { 3, 4, 5 } } };
int[,] nums6 = { { { 0, 1, 2 }, { 3, 4, 5 } } };

Масиви можуть мати і більшу кількість вимірів. Оголошення тривимірного масиву може мати такий вигляд:

int[,,,,] nums3 = new int[2, 3, 4];

Відповідно, можуть бути чотиривимірні масиви і масиви з великою кількістю вимірів. Але на практиці зазвичай використовуються одновимірні та двовимірні масиви.

Певну складність може представляти перерахування багатовимірного масиву. Перш за все, слід врахувати, що довжина такого масиву - це кумулятивна кількість елементів.

int[,] numbers = { { { 1, 2, 3 }, { 4, 5, 6 } } };
foreach (int i in numbers)
Console.Write($"\{i\} »);

У цьому випадку довжина масиву numbers дорівнює 6, а цикл foreach виводить всі елементи масиву в рядок:

1 2 3 4 5 6

Але що, якщо ми хочемо окремо виконати кожен рядок таблиці? У цьому випадку нам потрібно отримати кількість елементів у вимірі. Зокрема, в кожному масиві є метод GetUpperBound(dimension_number), який повертає індекс останнього елемента в певному вимірі. І якщо ми говоримо безпосередньо про двовимірний масив, то перший вимір (з індексом 0) по суті є таблицею. І з допомогою виразу

numbers.GetUpperBound(0) + 1

можна отримати кількість рядків таблиці, представленої двовимірним масивом. А з допомогою виразу

numbers.Length / number_rows

можна отримати кількість елементів у кожному рядку:

int[,] numbers = { { { 1, 2, 3 }, { 4, 5, 6 } } };

int rows = numbers.GetUpperBound(0) + 1; // кількість рядків
int columns = numbers.Length / rows; // кількість стовпців
// або на зразок
// int columns = numbers.GetUpperBound(1) + 1;

for (int i = 0; i < rows; i++)
{
for (int j = 0; j < columns; j++)
{
Console.Write({»{numbers[i, j]} \t)
}
Console.WriteLine();
}
1 2 3
4 5 6

Масив масивів

Від багатовимірних масивів слід відрізняти масив масивів або так званий «гвинтиковий масив»:

int[][] nums = new int[3][];
nums[0] = new int[2] { 1, 2 }; // виділити пам'ять для першого підмасиву
nums[1] = new int[3] { 1, 2, 3 }; // виділити пам'ять для другого підмасиву
nums[2] = new int[5] { 1, 2, 3, 4, 5 }; // виділити пам'ять для третього підмасиву

Тут дві групи квадратних дужок вказують на те, що це масив масивів, тобто масив, який в свою чергу містить інші масиви. Причому довжина масиву вказується тільки в перших квадратних дужках, всі наступні квадратні дужки повинні бути порожніми: new int[3][]. У даному випадку масив nums містить три масиви. Причому розмірність кожного з цих масивів може не співпадати.

Альтернативне визначення масиву масивів:

int[][] numbers = { 
new int[] { 1, 2 }
new int[] { 1, 2, 3 },
new int[] { 1, 2, 3, 4, 5 }
};

Незакреслені номери масивів

| 1 | 2 |
| 1 | 2 | 3 |
| 1 | 2 | 3 | 4 | 5 |

За допомогою вкладених циклів можна перебирати зубчасті масиви. Наприклад:

int[][] numbers = new int[3][];
numbers[0] = new int[] { 1, 2 };
numbers[1] = new int[] { 1, 2, 3 };
numbers[2] = new int[] { 1, 2, 3, 4, 5 };
foreach(int[] row in numbers)
{
foreach(int number in row)
{
Console.Write($«{number} \t»)
}
Console.WriteLine();
}

// цикл for
for (int i = 0; i<numbers.Length;i++)
{
for (int j = 0; j<numbers[i].Length; j++)
{
Console.Write($«{»{numbers[i][j]} \t)
}
Console.WriteLine();
}

Базові поняття про масиви

Наведемо основні поняття масивів:

  • Ранг: кількість вимірів масиву

  • Довжина виміру: довжина одного виміру масиву

  • Довжина масиву (довжина масиву): кількість усіх елементів масиву

Для прикладу, візьмемо масив

int[,] numbers = new int[3, 4];

Масив numbers двовимірний, тобто має два виміри, тому його ранг дорівнює 2. Довжина першого виміру дорівнює 3, а довжина другого виміру дорівнює 4. Довжина масиву (тобто загальна кількість елементів) дорівнює 12.