Обложка канала

.NET Разработчик

Опытный разработчик не так давно зашёл в .Net и поставил цель получить сертификат Microsoft. Свой ежедневный прогресс он описывает на канале .Net Разработчик. Заметки об изученном материале, советы по повышению производительности и поддержке мотивации, ин

.NET Разработчик

4 года назад
Открыть в
День 1180. #ЗаметкиНаПолях Выделяем Подмассивы. Окончание Начало Теперь рассмотрим второй способ. Для него рассмотрим новый сценарий. Допустим, мы создаем модель машинного обучения для благотворительной организации, которая будет предсказывать, сделает ли человек донат, в зависимости от его возраста. У нас есть куча данных, которые мы хотим разбить на две секции: обучающие данные, на которых будет обучаться модель, и тестовые данные, по которым мы будем тестировать модель.
var data = new (int, bool)[] {
  (20, true),
  (50, true),
  (35, false),
  (55, true),
  (16, false)
};

Заметьте, что в примере у нас всего 5 элементов. В реальной же модели обучения их могут быть миллионы, поэтому выделять новый массив будет очень затратно. 4. Использование ArraySegment<T>
var train = new ArraySegment<(int, bool)>(data, 0, 3);
var test = new ArraySegment<(int, bool)>(data, 3, 2);

Мы инициализируем новый экземпляр ArraySegment, передавая массив, который мы хотим разделить, начальный индекс и количество элементов. Это создает оболочку вокруг массива, которая ограничивает элементы между указанными позициями. Теперь мы можем выполнить итерацию по этому сегменту и прочитать его значения. То же самое можно сделать с помощью метода ArraySegment<T>.Slice():
var all = new ArraySegment<(int, bool)>(data);
var train = all.Slice(0, 3);
var test = all.Slice(3, 2);

Мы создаем ArraySegment, который охватывает весь массив, затем вызываем метод Slice(), который создает ещё один ArraySegment с указанными границами. Замечание: мы должны быть осторожны, потому что это не новый массив, это на самом деле переменная типа-значения, содержащая указатели на позиции элементов в массиве, поэтому любое изменение значений в сегменте массива будет отражаться в исходном массиве. 5. Использование ReadOnlySpan<T> и Span<T> ReadOnlySpan<T> предоставляет оболочку, которая позволяет только чтение из массива:
var train = new ReadOnlySpan<(int, bool)>(data, 0, 3);
var test = new ReadOnlySpan<(int, bool)>(data, 3, 2);

ReadOnlySpan очень похож на ArraySegment. Он принимает массив, начальный индекс и количество элементов. Мы можем перечислить его, но, если мы попытаемся изменить какой-либо элемент через экземпляр ReadOnlySpan, мы получим ошибку компиляции. Код, использующий Span<T> и его поведение аналогичны коду с ArraySegment<T>. Их отличие в том, что Span<T> можно использовать не только для массивов. Кроме того, ArraySegment<T> реализует IEnumerable<T> таким образом позволяет вернуть результат как IEnumerable<T>, тогда как ReadOnlySpan<T> и Span<T> возвращают соответствующие типы, хотя оба имеют метод GetEnumerator(), поэтому их также можно перечислить через foreach. Сравнение быстродействия На массиве из 10 строк быстродействие выделения подмассива из 5 элементов и их перечисления. Общий вид методов:
public int <Метод>()
{
  // получение подмассива указанным методом
  var slice = <подмассив>;
  var cnt = 0;
  foreach (var item in slice)
    cnt++;

  return cnt;
}
Результаты на картинке ниже. Источник: https://code-maze.com/csharp-array-slicing/