Как получить срез коллекции C#

C#

Введение в Array Slicing(срез массива) в C#

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

В C # появилось множество различных методов и операторов, которые можно использовать для слайсинга массивов.

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

Давайте перейдем к коду.

Срез массива используя LINQ

Допустим, у нас есть массив из десяти записей, и мы хотим вернуть пользователю только пять из них с намерением вернуть остальные по запросу. Это известно как пагинация и достигается с помощью двух методов LINQ Skip() и Take(). Итак, давайте импортируем LINQ и используем эти два метода:

Мы передаем количество элементов, которые мы хотим пропустить, методу Skip(). Это является начальным индексом, потому что если мы начинаем с индекса 0, то пропускаем 0 элементов и так далее. И мы передаем количество элементов, которые мы хотим получить в срезе, в метод Take(). Эта операция возвращает новый IEnumerable, который мы можем вывести на экран.

Использование метода Copy() для получения части массива

Давайте рассмотрим тот же сценарий, но на этот раз мы добьемся результата, используя метод Array Copy():

В этом коде мы создаем новый массив который будет хранить наш срез. И затем мы вызываем метод Copy(), который принимает исходный массив, начальный индекс, новый массив, начальный индекс нового массива(ноль, потому что мы копируем в новый массив), и кол-во элементов, которые мы хотим получить.

Как мы видим, этот метод работает так же, как и метод LINQ. Он возвращает новый массив, содержащий срез массива.

Теперь давайте рассмотрим новый подход к этой операции.

Срез массива используя ArraySegment<T>

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

ArraySegment<T> docs

 

Мы хотим разделить эти пять записей на обучающий набор из 3 записей и тестовый набор из 2 записей.

Итак, мы уже знаем пару способов сделать это, но давайте узнаем новый, используя ArraySegment<T>:

Мы инициализируем новый экземпляр ArraySegment, передавая массив, который мы хотим разделить, стартовый индекс, и количество элементов. Это создает оболочку вокруг массива, которая разделяет элементы между этими указанными позициями. Затем мы можем выполнить итерацию по этому сегменту и прочитать его значения.

То же самое может быть достигнуто с помощью метода ArraySegment<T>.Slice():

Мы создаем ArraySegment, который обертывает весь массив,затем вызываем метод Slice(), который создает другой ArraySegment с указанными границами, которые мы передаем ему в качестве параметров.

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

Мы увидим, что первые 3 элемента были изменены не только в сегменте массива, но и в исходном массиве:

Оператор Range (x..y) в C# 8.0+

Начиная с C# 8.0, появился новый оператор, который сделал слайсинг очень простым синтаксически. Это оператор диапазона x..y. Он позволяет нам разделять элементы между индексом ‘x’ и индексом ‘y’; индекс ‘y’ не включен:

Как мы видим, мы можем использовать либо оба операнда, либо никаких. Мы также можем видеть, что эти границы не работают в обратном направлении, поэтому slice5 выдает исключение ArgumentOutOfRangeException.

 

Добавить комментарий