Урок 6. Массивы и списки List<T>
Отметки за четверть, список покупок, координаты точек — часто нужно хранить не одно значение, а много. Для этого есть массивы и списки.
Массив
Массив — набор значений одного типа, у каждого свой номер — индекс. Индексы начинаются с нуля: у массива из пяти элементов они от 0 до 4.
int[] marks = { 7, 9, 6, 10, 8 };
Console.WriteLine(marks.Length);
Console.WriteLine(marks[0]);
Console.WriteLine(marks[marks.Length - 1]);
marks[2] = 5;
Console.WriteLine(string.Join(", ", marks));5
7
8
7, 9, 5, 10, 8int[]— тип «массив целых чисел»; значения перечисляют в фигурных скобках.marks.Length— сколько элементов в массиве.marks[0]— первый элемент,marks[marks.Length - 1]— последний (короче:marks[^1]).string.Join(", ", marks)склеивает элементы в строку через разделитель.
Размер массива задаётся при создании и потом не меняется. Пустой массив нужного размера создают через new: new int[5] — пять нулей, new string[3] — три пустые ссылки null, new bool[2] — два false.
Обращение к индексу за пределами массива — marks[5] у массива из пяти элементов — останавливает программу ошибкой IndexOutOfRangeException. Что с ней делать — в справке Ошибка IndexOutOfRangeException.
Обход массива
Пройти по элементам можно циклом for по индексам или foreach по значениям:
int[] marks = { 7, 9, 6, 10, 8 };
int sum = 0;
int max = marks[0];
foreach (int m in marks)
{
sum += m;
if (m > max)
{
max = m;
}
}
double average = (double)sum / marks.Length;
Console.WriteLine($"Сумма: {sum}, максимум: {max}");
Console.WriteLine($"Среднее: {average:F1}");Сумма: 40, максимум: 10
Среднее: 8,0foreach удобнее, когда нужны только значения. for нужен, если важен номер элемента или элементы нужно менять: marks[i] = 0;.
Сортировка и печать
int[] a = { 5, 3, 8, 1 };
Array.Sort(a);
Console.WriteLine(string.Join(" ", a));
Array.Reverse(a);
Console.WriteLine(string.Join(" ", a));
Console.WriteLine(a);1 3 5 8
8 5 3 1
System.Int32[]Array.Sort сортирует по возрастанию, Array.Reverse переворачивает. Обратите внимание на последнюю строку: Console.WriteLine(a) печатает не элементы, а название типа массива. Элементы выводят через string.Join или циклом.
Массив с клавиатуры
Числа обычно вводят в одной строке через пробел. Строку делят на части, а каждую часть переводят в число:
string[] parts = (Console.ReadLine() ?? "").Split(' ', StringSplitOptions.RemoveEmptyEntries);
int[] numbers = new int[parts.Length];
for (int i = 0; i < parts.Length; i++)
{
numbers[i] = int.Parse(parts[i]);
}
Console.WriteLine($"Чисел: {numbers.Length}, сумма: {numbers.Sum()}");4 8 15 16 23 42Чисел: 6, сумма: 108numbers.Sum() — готовая сумма из библиотеки LINQ (о ней — справка LINQ коротко). Цикл перевода можно записать одной строкой: int[] numbers = Array.ConvertAll(parts, int.Parse);.
Список List<T>
У массива постоянный размер. Если элементы нужно добавлять и удалять, берут список List<T>, где вместо T пишется тип элементов: List<int>, List<string>.
List<string> names = new List<string>();
names.Add("Анна");
names.Add("Борис");
names.Add("Вера");
Console.WriteLine(names.Count);
names.Insert(1, "Глеб");
Console.WriteLine(string.Join(", ", names));
names.Remove("Борис");
names.RemoveAt(0);
Console.WriteLine(string.Join(", ", names));
Console.WriteLine(names.Contains("Вера"));
Console.WriteLine(names[0]);3
Анна, Глеб, Борис, Вера
Глеб, Вера
True
Глеб| Что сделать | Как |
|---|---|
| добавить в конец | list.Add(x) |
вставить на место i | list.Insert(i, x) |
| удалить значение (первое найденное) | list.Remove(x) |
| удалить по индексу | list.RemoveAt(i) |
| сколько элементов | list.Count (у массива — Length) |
| есть ли значение | list.Contains(x) |
| где значение | list.IndexOf(x) — индекс или −1 |
| отсортировать | list.Sort() |
| очистить | list.Clear() |
Список можно сразу заполнить: var primes = new List<int> { 2, 3, 5, 7 };.
Пример: числа до нуля
Сколько чисел введут, заранее неизвестно — тут список удобнее массива:
List<int> numbers = new List<int>();
while (true)
{
int x = int.Parse(Console.ReadLine() ?? "");
if (x == 0)
{
break;
}
numbers.Add(x);
}
numbers.Sort();
Console.WriteLine($"Введено: {numbers.Count}");
Console.WriteLine($"По возрастанию: {string.Join(" ", numbers)}");5
2
9
1
0Введено: 4
По возрастанию: 1 2 5 9Массив — это ссылка
Переменная массива или списка хранит не сами элементы, а ссылку на них. Присваивание копирует ссылку, и две переменные смотрят на один и тот же массив:
int[] a = { 1, 2, 3 };
int[] b = a;
b[0] = 100;
Console.WriteLine(a[0]);100Настоящую копию делает (int[])a.Clone() или a.ToArray(), копию списка — new List<int>(list).
Двумерные массивы
Таблицу чисел хранит двумерный массив: int[,] grid = new int[3, 4]; — 3 строки по 4 столбца. Элемент — grid[1, 2], число строк — grid.GetLength(0), столбцов — grid.GetLength(1). Обходят его двумя вложенными циклами for.
Коротко
- Массив:
int[] a = { 1, 2, 3 };илиnew int[n]; индексы от 0 доa.Length - 1, размер не меняется. Array.Sort(a),Array.Reverse(a); печать —string.Join(", ", a), а неConsole.WriteLine(a).- Список
List<T>:Add,Insert,Remove,RemoveAt,Contains,Sort, размер —Count. - Массив из строки ввода —
Splitиint.Parseдля каждой части. - Присваивание массива или списка копирует ссылку, а не элементы.