Перейти к содержимому
Теория · Массивы · урок 7 из 9

Индекс с конца и диапазоны

В раздевалке последний шкафчик ряда находят, не зная его номера: идут к концу ряда. А вещи из нескольких соседних шкафчиков забирают за один подход, не называя шкафчики по одному.

С массивом так пока не получается. Чтобы прочитать последний элемент, нужно вычислить его индекс: nums[nums.Length - 1]. А чтобы взять несколько элементов подряд, нужен цикл, который скопирует их в новый массив. В C# для обоих случаев есть короткие формы.

Индекс с конца

Последний элемент можно получить короче: nums[^1]. Знак ^ перед числом делает его индексом с конца, и ^n означает «n-й элемент с конца»:

  • ^1 — последний элемент, тот же, что по индексу Length - 1;
  • ^2 — предпоследний.

Счёт с конца начинается с единицы, а не с нуля. ^0 указывает на место сразу за последним элементом, как индекс Length.

Диапазон

Диапазон nums[1..3] берёт часть массива: элементы от индекса 1 до индекса 3. Начало входит в диапазон, а конец — нет, поэтому это элементы с индексами 1 и 2. Любую из границ или обе сразу можно не писать:

  • nums[..2] — от начала до индекса 2, то есть два первых элемента;
  • nums[3..] — от индекса 3 до конца массива;
  • nums[^2..] — два последних элемента;
  • nums[..] — весь массив, от начала до конца.
C#
int[] nums = [10, 20, 30, 40, 50];
Console.WriteLine(nums[^1]); // 50
int[] middle = nums[1..3];
Console.WriteLine(string.Join(", ", middle)); // 20, 30
Console.WriteLine(string.Join(", ", nums[..2])); // 10, 20
Console.WriteLine(string.Join(", ", nums[3..])); // 40, 50
middle[0] = 99;
Console.WriteLine(nums[1]); // 20

Диапазон массива создаёт новый массив и копирует в него элементы. Поэтому middle[0] = 99 меняет только копию, а nums[1] по-прежнему равен 20.

Так же работает и nums[..]: это копия всего массива. Если нужен и отсортированный массив, и прежний порядок, сохраните копию, int[] sorted = nums[..];, и отсортируйте её через Array.Sort.

Здесь картинка со шкафчиками неточна. В раздевалке «шкафчики 1 и 2» — это те же самые шкафчики. Диапазон массива ставит новый короткий ряд и перекладывает в него копии вещей.

На собеседовании часто спрашивают, входит ли конец диапазона в результат. Не входит: в nums[1..3] элементов 3 - 1, то есть два.

Частая ошибка

Последний элемент попытались прочитать через ^0:

C#
int[] nums = [10, 20, 30];
Console.WriteLine(nums[^0]); // ✗
TEXT
Unhandled exception. System.IndexOutOfRangeException: Index was outside the bounds of the array.

Программа компилируется, но при запуске останавливается на этой строке с исключением IndexOutOfRangeException. ^0 указывает за последний элемент, ведь счёт с конца начинается с единицы. Последний элемент — nums[^1].

Главное

  • nums[^1] — последний элемент: счёт с конца начинается с единицы, а ^0 указывает за конец массива.
  • nums[1..3] — новый массив из элементов с индексами 1 и 2: конец диапазона не входит, а изменения копии не трогают оригинал.
  • nums[..] — копия всего массива.