Список List
В статье рассмотрим принципы работы со списком List: создание списка и обращение к данными; добавление, удаление, поиск и сортировка элементов. Есть несколько вариантов создания списка: Нет ограничений на тип, который можно поместить в список. Надо заметить, что это не то же самое, что и Больше полезных материалов вы найдете на нашем телеграм-канале «Библиотека шарписта» Интересно, перейти к каналу Если вывести все значения из списка Также рассмотрим более сложный пример с пользовательским классом. Помимо перечисленных выше конструкторов, есть еще один, который принимает размер начальной емкости списка: Внутри списка находится массив, который при заполнении определенной емкости динамически расширяется, чтобы снизить издержки на выделение памяти при добавлении элементов. На низком уровне при проверке расширения проверяется, если в массиве (который внутри списка) нет элементов, то его размер выставляется равным Аналогично как в массиве, допустимо обращаться к элементам списка в квадратных скобках по индексу. Доступ к элементам списка Для определения длины списка используется свойство Получение длины списка Для перебора списка можно использовать классический цикл, например Перебор списка for Также существует специальный цикл для работы со списками Перебор списка foreach Наконец, добрались до самого интересного — методы, которые улучшают работу со списком по сравнении с массивом. Рассмотрим следующие методы (полный список методов можно посмотреть в документации Microsoft): В этом примере мы создадим массив и разными способами заполним его в цикле. Удаление данных из списка Работа с диапазоном Построение элементов в обратном порядке *** В статье рассмотрена работа с коллекцией Список List<T>
List<T>
— класс из пространства имен System.Collections.Generic
, список однотипных объектов. В отличие от массива, предоставляет набор методов, облегчающих работу, таких как добавление новых элементов (это удобно, когда неизвестно заранее сколько будет элементов).Создание списка без начальных значений
//List<T> list = new List<T>(); //T - выбранный тип, например int //Пример: List<int> list = new List<int>(); //Примеры других типов: List<string> sList = new List<string>(); List<object> oList = new List<object>();
Создание списка с начальными значениями
//List<T> list = new List<T>(){ Item1, Item2, Item3… }; //Item1/2/3 - элементы нашего списка, тип которых T //List<T> list = new List<T>{ Item1, Item2, Item3… }; // Тоже допустимо //Пример: List<int> list = new List<int> { 1, 2, 3 }; //Мы создали список с набором чисел
Создание на основе другого списка
List<int> list = new List<int> { 1, 2, 3 }; List<int> list2 = new List<int>(list);
list2 = list
, т. к. при передаче списка в конструктор нового списка создается именно новый список, т. е. в памяти выделяется место для нового объекта, но заполняется теми же значениями, которые были в переданном списке.Комбинированный подход
List<int> list = new List<int> { 1, 2, 3 }; List<int> list2 = new List<int>(list) { 4 };
list2
, будут выведены значения от 1 до 4.
class Cup { public string Name { get; set; } public int Capacity { get; set; } public ConsoleColor Color { get; set; } public Cup(string name) { Name = name; } } List<Cup> cups = new List<Cup> { new Cup("Моя кружка") { Color = ConsoleColor.White, Capacity = 1000 }, new Cup("Не моя кружка") { Color = ConsoleColor.Black, Capacity = 300 } };
Установка начальной емкости списка
List<int> list = new List<int>(10);
_defaultCapacity
(переменная в исходниках, которая имеет начальное значение = 4), в противном случае считается из «количество элементов» * 2. Т. е. всякий раз, когда мы достигаем определенной границы массива, List
автоматически расширяет его в 2 раза, однако ограничение списка — это 2G (Array.MaxArrayLength – 2146435071) элементов. Для повышения производительности, если известен конечный размер списка, можно изначально задать его размер, что избавит от дополнительных выделений памяти.Обращение к элементам списка
List<int> list = new List<int>() { 3, 4, 2, 0 }; Console.WriteLine(list[0]);// 3 list[0] = 7; Console.WriteLine(list[0]);// 7 List<int> list1 = new List<int>(); list1[0] = 1; // Получим исключение ArgumentOutOfRangeException, т.е. для начала нужно создать хоть один элемент списка
Длина списка
Count
.
List<int> list = new List<int>() { 3, 4, 2, 0 }; Console.WriteLine(list.Count); // 4 list = new List<int>(); Console.WriteLine(list.Count); // 0
Перебор списка
for
.
List<int> list = new List<int>() { 3, 4, 2, 0 }; for(int i = 0; i < list.Count; i++) Console.WriteLine(list[i]);
foreach
.
List<int> list = new List<int>() { 3, 4, 2, 0 }; foreach(int item in list) Console.WriteLine(item);
Методы списка
Добавление в список
void Add(T item)
— добавляет новый элемент с типом T
в конец списка.void AddRange(IEnumerable<T> collection)
— добавляет в список коллекцию или массив в конец списка.void Insert(int index, T item)
— вставляет элемент в коллекцию по указанному индексу. При выходе за границы коллекции (0 > index или Count-1 < index)
будет сформировано исключение System.ArgumentOutOfRangeException
.void InsertRange(int index, IEnumerable<T> collection)
— аналогично методу выше, только вставляет список элементов по указанному индексу. Также при выходе за границы будет сформировано исключение System.ArgumentOutOfRangeException
.Поиск и проверка элемента
int BinarySearch(T item)
— бинарный поиск элемента в списке, возвращает индекс элемента. Работает корректно, если список отсортирован. Имеет еще два варианта реализации с дополнительными параметрами для корректного сравнения элементов или указания начальной точки поиска.bool Contains(T item)
— проверка наличия элемента в списке.bool Exists(Predicate<T> match)
— проверяет наличие в списке хотя бы одного элемента удовлетворяющего условиям делегата match
.T Find(Predicate<T> match)
— возвращает первый элемент, удовлетворяющий условиям делегата match
.List<T> FindAll(Predicate<T> match)
— аналогичен Find
, только возвращает все элементы.int FindIndex(Predicate<T> match)
— возвращает первый индекс элемента, удовлетворяющего условиям делегата match
. Имеет еще два варианта реализации с указанием позиции поиска и количества элементов.int FindLastIndex(Predicate<T> match)
— аналогично FindIndex
, только возвращает индекс последнего элемента, удовлетворяющего условиям делегата match
. Также имеет еще два варианта реализации с указанием позиции поиска и количества элементов.List<T> GetRange(int index, int count)
— этот метод получает подсписок из списка от указанного индекса с указанным количеством элементов.int IndexOf(T item)
— возвращает первый индекс элемента, если он найден в списке либо -1
. Также имеет еще два реализации с указанием позиции поиска и количества элементов.int LastIndexOf(T item)
— возвращает последний индекс элемента, если он найден в списке либо -1
. Также имеет еще два реализации с указанием позиции поиска и количества элементов.Удаление из списка
bool Remove(T item)
— удаляет первое вхождение указанного элемента из списка. Возвращает true
, если элемент был удален или false
, если нет.int RemoveAll(Predicate<T> match)
— удаляет все элементы, удовлетворяющие условиям делегата match
. Возвращает количество удаленных элементов.void RemoveAt(int index)
— удаляет элемент списка с указанным индексом. При выходе индекса за границы списка формирует исключение System.ArgumentOutOfRangeException
.void RemoveRange(int index, int count)
— удаляет элементы массива с указанного индекса в указанном количестве. Если index
меньше 0 или значение параметра count меньше 0, то будет сформировано исключение System.ArgumentOutOfRangeException
. Если параметры index
и count
не указывают допустимый диапазон элементов в списке, будет сформировано исключение System.ArgumentException
.void Clear()
— удаляет все элементы из списка.Сортировка списка
void Sort()
— сортирует элементы. В основе лежит алгоритм быстрой сортировки с ограничением глубины рекурсии до 32, при достижении которого используется сортировка кучей.void Reverse()
— изменяет порядок элементов во всем списке на обратный. Имеет перегруженную версию, в которой указывается начальный индекс и количество элементов.Прочее
List<TOutput> ConvertAll<TOutput>(Converter<T, TOutput> converter)
— позволяет сконвертировать все типы элементов текущего списка в другой тип. На входе принимает делегат на метод, преобразующий объект от одного типа к другому.void CopyTo(T[] array)
— копирует список в массив. Имеет еще 2 варианта реализации с указанием границ и позиций копирования.void ForEach(Action<T> action)
— это аналог цикла foreach
, только в качестве итерации будет выполняться метод, который на входе принимает элемент с типом T
. Еще одно отличие такого цикла от foreach
состоит в том, что в методе не сработает ни break
, ни continue
. Аналогом continue
при таком подходе можно считать return
.T[] ToArray()
— возвращает массив элементов списка.Примеры
Добавление в список
List<int> list = new List<int>(); for (int i = 0; i < 10; i++) { list.Add(i); // Добавление элемента в конец списка list.AddRange(new[] { i + 4, i + 5 }); // Добавление коллекции элементов в конец списка list.Insert(i, i + 1); // Вставка элемента по индексу i list.InsertRange(i, new[] { i + 2, i + 3 }); // Вставка массива/коллекции по индексу i }
Удаление из списка
List<int> list = new List<int>() { 0, 1, 2, 9, 32, -7 }; // Создали массив с элементами Console.WriteLine(string.Join(",", list)); if (list.Remove(9)) // Удаляем 9 Console.WriteLine("Элемент 9 успешно удален."); Console.WriteLine(string.Join(",", list)); list.RemoveAt(0); // Удаляем 0 Console.WriteLine(string.Join(",", list)); list.RemoveAll(i => i < 0); // Удаляем -7 Console.WriteLine(string.Join(",", list)); list.RemoveRange(0, 2); // Удаляес 1 и 2 Console.WriteLine(string.Join(",", list)); list.Clear(); // Удаляем все оставшиеся элементы - 32 Console.WriteLine(string.Join(",", list));
Поиск и проверка элемента
List<int> list = new List<int> { 0, 0, 1, -7, 9, 2, 32, 16, 42 }; //Индексы //Поиск первого четного индекса Console.WriteLine(list.FindIndex(i => i % 2 == 0)); // 0 //Поиск последнего четного индекса Console.WriteLine(list.FindLastIndex(i => i % 2 == 0)); // 8 //Поиск индекса по числу из списка Console.WriteLine(list.IndexOf(-7)); // 3 //Попробуем найти индекс числа которого нет в списке Console.WriteLine(list.IndexOf(13)); // -1 //Поиск последнего индекса по числу из списка Console.WriteLine(list.LastIndexOf(0)); // 1 list.Sort(); // Отсортируем массив, так как это основное условие бинарного поиска Console.WriteLine(list.BinarySearch(9)); // 5 //Проверка вхождения //Проверим есть ли в списке четные числа Console.WriteLine(list.Exists(i => i % 2 == 0)); // true Console.WriteLine(list.Contains(0)); // true Console.WriteLine(list.Contains(13)); // false //Значения //А теперь получим первое четное число Console.WriteLine(list.Find(i => i % 2 == 0)); // 0 //Найдем все четные числа Console.WriteLine(string.Join(",", list.FindAll(i => i % 2 == 0))); // 0,0,2,16,32,42 //Последнее четное число Console.WriteLine(string.Join(",", list.FindLast(i => i % 2 == 0))); // 42 //Получим подсписок, первые 4 элемента Console.WriteLine(string.Join(",", list.GetRange(0, 4))); // -7,0,0,1
Получение диапазона и копирование в массив
List<int> list = new List<int> { 0, 0, 1, -7, 9, 2, 32, 16, 42 }; var range = list.GetRange(2, 3); // Получим диапазон/подсписок int[] part = new int[range.Count]; // Объявим массив куда будем копировать диапазон range.CopyTo(part); // Скопируем диапазон Console.WriteLine(string.Join(",", part)); // 1,-7,9
Расположение элементов в обратном порядке
List<int> list = new List<int> { 0, 0, 1, -7, 9, 2, 32, 16, 42 }; list.Reverse(); Console.WriteLine(string.Join(",", list)); // 42,16,32,2,9,-7,1,0,0 list.Reverse(1, 3); Console.WriteLine(string.Join(",", list)); // 42,2,32,16,9,-7,1,0,0
List
, рассмотрена базовая работа (инициализация, обращение к данными) и методы для работы со списком:Материалы по теме
- 0 views
- 0 Comment