Как создать список в с
Перейти к содержимому

Как создать список в с

  • автор:

Коллекции

Хотя в языке C# есть массивы, которые хранят в себе наборы однотипных объектов, но работать с ними не всегда удобно. Например, массив хранит фиксированное количество объектов, однако что если мы заранее не знаем, сколько нам потребуется объектов. И в этом случае намного удобнее применять коллекции. Еще один плюс коллекций состоит в том, что некоторые из них реализует стандартные структуры данных, например, стек, очередь, словарь, которые могут пригодиться для решения различных специальных задач. Большая часть классов коллекций содержится в пространстве имен System.Collections.Generic .

Класс List из пространства имен System.Collections.Generic представляет простейший список однотипных объектов. Класс List типизируется типом, объекты которого будут хранится в списке.

Мы можем создать пустой список:

List people = new List();

В данном случае объект List типизируется типом string . А это значит, что хранить в этом списке мы можем только строки.

Можно сразу при создании списка инициализировать его начальными значениями. В этом случае элементы списка помещаются после вызова конструктора в фигурных скобках

List people = new List() < "Tom", "Bob", "Sam" >;

В данном случае в список помещаются три строки

Также можно при создании списка инициализировать его элементами из другой коллекции, например, другого списка:

var people = new List() < "Tom", "Bob", "Sam" >; var employees = new List(people);

Можно совместить оба способа:

var people = new List() < "Tom", "Bob", "Sam" >; var employees = new List(people);

В данном случае в списке employees будет четыре элемента ( < "Tom", "Bob", "Sam", "Mike" >) — три добавляются из списка people и один элемент задается при инициализации.

Подобным образом можно работать со списками других типов, например:

List people = new List() < new Person("Tom"), new Person("Bob"), new Person("Sam") >; class Person < public string Name < get;>public Person(string name) => Name = name; >

Установка начальной емкости списка

Еще один конструктор класса List принимает в качестве параметра начальную емкость списка:

List people = new List(16);

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

Также начальную емкость можно установить с помощью свойства Capacity , которое имеется у класса List.

Обращение к элементам списка

Как и массивы, списки поддерживают индексы, с помощью которых можно обратиться к определенным элементам:

var people = new List() < "Tom", "Bob", "Sam" >; string firstPerson = people[0]; // получаем первый элемент Console.WriteLine(firstPerson); // Tom people[0] = "Mike"; // изменяем первый элемент Console.WriteLine(people[0]); // Mike

Длина списка

С помощью свойства Count можно получить длину списка:

var people = new List() < "Tom", "Bob", "Sam" >; Console.WriteLine(people.Count); // 3

Перебор списка

C# позволяет осуществить перебор списка с помощью стандартного цикла foreach :/p>

var people = new List() < "Tom", "Bob", "Sam" >; foreach (var person in people) < Console.WriteLine(person); >// Вывод программы: // Tom // Bob // Sam

Также можно использовать другие типы циклов и в комбинации с индексами перебирать списки:

var people = new List() < "Tom", "Bob", "Sam" >; for (int i = 0; i

Методы списка

Среди его методов можно выделить следующие:

  • void Add(T item) : добавление нового элемента в список
  • void AddRange(IEnumerable collection) : добавление в список коллекции или массива
  • int BinarySearch(T item) : бинарный поиск элемента в списке. Если элемент найден, то метод возвращает индекс этого элемента в коллекции. При этом список должен быть отсортирован.
  • void CopyTo(T[] array) : копирует список в массив array
  • void CopyTo(int index, T[] array, int arrayIndex, int count) : копирует из списка начиная с индекса index элементы, количество которых равно count, и вставляет их в массив array начиная с индекса arrayIndex
  • bool Contains(T item) : возвращает true , если элемент item есть в списке
  • void Clear() : удаляет из списка все элементы
  • bool Exists(Predicate match) : возвращает true , если в списке есть элемент, который соответствует делегату match
  • T? Find(Predicate match) : возвращает первый элемент, который соответствует делегату match. Если элемент не найден, возвращается null
  • T? FindLast(Predicate match) : возвращает последний элемент, который соответствует делегату match. Если элемент не найден, возвращается null
  • List FindAll(Predicate match) : возвращает список элементов, которые соответствуют делегату match
  • int IndexOf(T item) : возвращает индекс первого вхождения элемента в списке
  • int LastIndexOf(T item) : возвращает индекс последнего вхождения элемента в списке
  • List GetRange(int index, int count) : возвращает список элементов, количество которых равно count, начиная с индекса index.
  • void Insert(int index, T item) : вставляет элемент item в список по индексу index. Если такого индекса в списке нет, то генерируется исключение
  • void InsertRange(int index, collection) : вставляет коллекцию элементов collection в текущий список начиная с индекса index. Если такого индекса в списке нет, то генерируется исключение
  • bool Remove(T item) : удаляет элемент item из списка, и если удаление прошло успешно, то возвращает true. Если в списке несколько одинаковых элементов, то удаляется только первый из них
  • void RemoveAt(int index) : удаление элемента по указанному индексу index. Если такого индекса в списке нет, то генерируется исключение
  • void RemoveRange(int index, int count) : параметр index задает индекс, с которого надо удалить элементы, а параметр count задает количество удаляемых элементов.
  • int RemoveAll((Predicate match)) : удаляет все элементы, которые соответствуют делегату match. Возвращает количество удаленных элементов
  • void Reverse() : изменяет порядок элементов
  • void Reverse(int index, int count) : изменяет порядок на обратный для элементов, количество которых равно count, начиная с индекса index
  • void Sort() : сортировка списка
  • void Sort(IComparer? comparer) : сортировка списка с помощью объекта comparer, который передается в качестве параметра

Добавление в список

List people = new List () < "Tom" >; people.Add("Bob"); // добавление элемента // people = < "Tom", "Bob" >; people.AddRange(new[] < "Sam", "Alice" >); // добавляем массив // people = < "Tom", "Bob", "Sam", "Alice" >; // также можно было бы добавить другой список // people.AddRange(new List()< "Sam", "Alice" >); people.Insert(0, "Eugene"); // вставляем на первое место // people = < "Eugene", "Tom", "Bob", "Sam", "Alice" >; people.InsertRange(1, new string[] ); // вставляем массив с индекса 1 // people = < "Eugene", "Mike", "Kate", "Tom", "Bob", "Sam", "Alice" >; // также можно было бы добавить другой список // people.InsertRange(1, new List()< "Mike", "Kate" >);

Удаление из списка

var people = new List () < "Eugene", "Mike", "Kate", "Tom", "Bob", "Sam", "Tom", "Alice" >; people.RemoveAt(1); // удаляем второй элемент // people = < "Eugene", "Kate", "Tom", "Bob", "Sam", "Tom", "Alice" >; people.Remove("Tom"); // удаляем элемент "Tom" // people = < "Eugene", "Kate", "Bob", "Sam", "Tom", "Alice" >; // удаляем из списка все элементы, длина строки которых равна 3 people.RemoveAll(person => person.Length == 3); // people = < "Eugene", "Kate", "Alice" >; // удаляем из списка 2 элемента начиная с индекса 1 people.RemoveRange(1, 2); // people = < "Eugene">; // полностью очищаем список people.Clear(); // people = < >;

Поиск и проверка элемента

var people = new List () < "Eugene", "Mike", "Kate", "Tom", "Bob", "Sam" >; var containsBob = people.Contains(«Bob»); // true var containsBill = people.Contains(«Bill»); // false // проверяем, есть ли в списке строки с длиной 3 символа var existsLength3 = people.Exists(p => p.Length == 3); // true // проверяем, есть ли в списке строки с длиной 7 символов var existsLength7 = people.Exists(p => p.Length == 7); // false // получаем первый элемент с длиной в 3 символа var firstWithLength3 = people.Find(p => p.Length == 3); // Tom // получаем последний элемент с длиной в 3 символа var lastWithLength3 = people.FindLast(p => p.Length == 3); // Sam // получаем все элементы с длиной в 3 символа в виде списка List peopleWithLength3 = people.FindAll(p => p.Length == 3); // peopleWithLength3

Получение диапазона и копирование в массив

List people = new List() ; // получаем диапазон со второго по четвертый элемент var range = people.GetRange(1, 3); // range = < "Tom", "Mike", "Sam">; // копируем в массив первые три элемента string[] partOfPeople = new string[3]; people.CopyTo(0, partOfPeople, 0, 3); // partOfPeople = < "Eugene", "Tom", "Mike">;

Расположение элементов в обратном порядке

var people = new List () < "Eugene", "Tom", "Mike", "Sam", "Bob" >; // переворачиваем весь список people.Reverse(); // people = < "Bob","Sam", "Mike", "Tom", "Eugene">; var people2 = new List() < "Eugene", "Tom", "Mike", "Sam", "Bob" >; // переворачиваем часть только 3 элемента с индекса 1 people2.Reverse(1, 3); // people2 = < "Eugene","Sam", "Mike", "Tom", "Bob" >;

Списки

C# имеет ряд классов для работы со списками. Они реализуют Интерфейс IList и наиболее популярной реализацией является общий список, часто называемый List&ltT>. T указывает Тип объектов, содержащихся в списке, который имеет дополнительное преимущество, что компилятор будет проверять и убедится, что вы добавите только объекты нужного типа в список — другими словами, List является типобезопасным.

List очень похож на класс ArrayList, который был вариантом go-to List до C# поддерживаемых универсальных списков. Поэтому вы также увидите, что List может делать много того же, что и массив (который, кстати, также реализует Интерфейс IList), но во многих ситуациях с List проще и легче работать. Например, вам не нужно создавать список определенного размера — вместо этого вы можете просто создать его, и .NET автоматически развернет его в соответствии с количеством элементов по мере их добавления.

Как уже упоминалось, T обозначает тип и используется для указания типа объектов, которые должны содержаться в списке. В нашем первом примере, я покажу вам, как создать список, который должен содержать строки:

List listOfStrings = new List();

Это создает пустой список, но, легко добавляя в него впоследствии с помощью метода Add:

listOfStrings.Add("a string");

Однако, если вы попробуете добавить что-нибудь, что не является символьной строкой, компилятор немедленно пожалуется на это:

listOfStrings.Add(2);
Error CS1503 Argument 1: cannot convert from 'int' to 'string'

Инициализация списка с элементами

В приведенном выше примере мы просто создали список, а затем добавили в него элемент. Однако C# фактически позволяет создавать список и добавлять в него элементы в пределах одной инструкции, используя метод, называемый инициализаторами коллекций. Давайте посмотрим, как это делается:

List listOfNames = new List()
"John Doe",
"Jane Doe",
"Joe Doe"
>;

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

Работа с элементами

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

using System;
using System.Collections.Generic;

namespace Lists
class Program
static void Main(string[] args)
List listOfUsers = new List()
new User() < Name = "John Doe", Age = 42 >,
new User() < Name = "Jane Doe", Age = 34 >,
new User() < Name = "Joe Doe", Age = 8 >,
>;

for(int i = 0; i < listOfUsers.Count; i++)
Console.WriteLine(listOfUsers[i].Name + " is " + listOfUsers[i].Age + " years old");
>
Console.ReadKey();
>
>

class User
public string Name < get; set; >

public int Age < get; set; >
>
>

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

Как только список готов, я использую цикл for для его выполнения — чтобы узнать, сколько итераций мы собираемся сделать, я использую свойство Count списка. На каждой итерации я обращаюсь к рассматриваемому пользователю через индексатор списка, используя синтаксис квадратных скобок (например, listOfUsers[i]). Так как у меня есть пользователь, я вывожу имя и возраст.

Добавление, вставка и удаление элементов

Мы уже пытались добавить один элемент в список, но есть больше возможностей для этого. Прежде всего, вы можете вставить элемент вместо добавления — разница в том, что в то время как метод Add всегда добавляет в конец списка, метод Insert позволяет вставить элемент в определенной позиции. Вот пример:

List listOfNames = new List()
"Joe Doe"
>;
// Insert at the top (index 0)
listOfNames.Insert(0, "John Doe");
// Insert in the middle (index 1)
listOfNames.Insert(1, "Jane Doe");

Сначала мы создаём один элемент в списке, потом добавляем еще два — один вверху списка, второй посередине. Первый параметр метода Insert означает индекс, который определяет порядок элемента. Второй же имеет само значение элемента. Осторожно — будет выдано исключение, если вставить элемент с индексом 3, если в списке меньше элементов.

Добавление нескольких элементов

Так же как у нас есть методы Add и Insert для добавления и вставки одного элемента, также есть соответствующие методы для добавления и вставки нескольких элементов. Они называются AddRange() и InsertRange() и принимают любой тип из коллекции, который как параметр реализует интерфейс IEnumerable — это, например, может быть массив элементов или список, элементы которого вы хотите добавить или вставить в текущий список.

Для примера метода Range давайте сделаем что-нибудь забавное — мы объединим метод AddRange с инициализатором коллекции, чтобы добавить несколько новых имен в существующий список в одном операторе:

listOfNames.AddRange(new string[] 
"Jenna Doe",
"Another Doe"
>);

Мы просто создали массив строк на-лету и немедленно добавили эти элементы в наш список имен из предыдущего примера.

Удаление элементов

Cуществуют три способа удаления одного или нескольких элементов из списка: Remove(), RemoveAt() and RemoveAll().

Метод Remove() принимает лишь один параметр: элемент, который нужно удалить. Это прекрасно подходит, например, для так списка строк или чисел, потому что вы можете просто вписать элемент, который хотите удалить. С другой стороны, если у вас есть список сложных объектов, вам придется сначала найти этот объект, чтобы была ссылка, которую можно передать в метод Remove (). «Давайте разберемся с этим позже» — вот очень простой пример того, как вы можете удалить один элемент с помощью метода Remove:

List listOfNames = new List()
"John Doe",
"Jane Doe",
"Joe Doe",
"Another Doe"
>;

listOfNames.Remove("Joe Doe");

Метод Remove() просто перебирает список, пока не находит первое вхождение объекта вы указали для удаления и удаляет его — он удаляет только один экземпляр, и если указанный вами пункт в списке, не существует, ошибка не выдается. Метод возвращает true, если удалось удалить элемент, и false, если это не так.

Метод RemoveAt () использует тот факт, что универсальный список основан на индексе, позволяя удалить элемент на основе его индекса/позиции в списке. Например, вы можете удалить первый элемент из списка следующим образом:

listOfNames.RemoveAt(0);

Или последний элемент списка как здесь:

listOfNames.RemoveAt(listOfNames.Count - 1);

Опять же, это удаляет только один элемент, и на этот раз вы должны быть осторожны при предоставлении индекса удаляемого элемента — если вы используете индекс, который выходит за пределы (ниже 0 или выше количества элементов), будет выдано исключение! Таким образом, если Вы не уверены в том, что вы делаете, вы можете обернуть метод RemoveAt() в блок try-catch для обработки исключения (подробно описано в других разделах этого руководства). Метод RemoveAt() ничего не возвращает, поэтому вам придется проверить количество элементов в списке до и после вызова, чтобы решить, был ли он успешным — с другой стороны, если вы знаете, что у вас есть индекс, который существует в списке, о котором вы всегда должны убедиться, то вы всегда можете ожидать, что RemoveAt () будет успешным.

Метод removeall() — это наиболее сложный из удаляющих-методов, но наверняка также самый мощный. Он принимает делегат метода в качестве параметра, и этот метод затем решает, следует ли удалить элемент или нет, возвращая true или false. Он позволяет применять собственную логику при удалении элементов, а также позволяет удалять несколько элементов одновременно. Делегаты будут рассмотрены в другом месте этого учебника, поскольку это большая и сложная тема, но я все равно хочу, чтобы вы почувствовали, насколько крут метод RemoveAll, поэтому вот пример:

List listOfNames = new List()
"John Doe",
"Jane Doe",
"Joe Doe",
"Another Doe"
>;

listOfNames.RemoveAll(name =>
if (name.StartsWith("J"))
return true;
else
return false;
>);

В этом примере в качестве параметра метода RemoveAll используется анонимный метод (опять же слишком сложный для объяснения, но он будет рассматриваться в другой главе). Наш анонимный метод довольно прост — он будет вызываться для каждого элемента в списке и иметь параметр с именем name, который, конечно же, является текущим элементом в итерации. Он смотрит на это имя, и если оно начинается с «J», возвращаетсяtrue — в противном случаеfalse . Метод RemoveAll () использует этот ответ (true или false), чтобы решить, следует ли удалять каждый элемент. В конце концов, это оставляет наш первоначальный список только с одним членом Doe: Another Doe.

Сортировка элементов

До сих пор элементы списка, с которыми мы работали, использовались только в том порядке, в котором они были добавлены в список. Тем не менее, вы можете отсортировать элементы определенным образом, например, по алфавиту в случае нашего списка имен. List имеет метод сортировки (), который мы можем использовать для этого:

List listOfNames = new List()
"John Doe",
"Jane Doe",
"Joe Doe",
"Another Doe"
>;
listOfNames.Sort();
foreach (string name in listOfNames)
Console.WriteLine(name);

Как вы увидите из выходных данных, элементы в списке теперь отсортированы по алфавиту, и если вы хотите, чтобы он был в порядке убывания (от Z до A), просто вызовите метод Reverse () после выполнения сортировки:

listOfNames.Sort();
listOfNames.Reverse();

Итак, сортировать список было довольно легко, верно? Ну, это было в основном так просто, потому что у нас есть список строк, и .NET framework точно знает, как сравнивать две строки. Если у вас есть список чисел, .NET, конечно же, знает, как это сортировать. С другой стороны, у вас может быть список пользовательских объектов (поскольку список может содержать любой объект), который .NET не имеет возможности сравнить. Есть несколько решений этой проблемы, например, реализация интерфейса IComparable или использование LINQ (мы рассмотрим оба позже в этом уроке), но в качестве быстрого исправления мы также можем просто предоставить метод для вызова метода Sort (), чтобы узнать, как два элемента складываются друг против друга, как здесь:

using System;
using System.Collections.Generic;

namespace ListSort
class Program
static void Main(string[] args)
List listOfUsers = new List()
new User() < Name = "John Doe", Age = 42 >,
new User() < Name = "Jane Doe", Age = 39 >,
new User() < Name = "Joe Doe", Age = 13 >,
>;
listOfUsers.Sort(CompareUsers);
foreach (User user in listOfUsers)
Console.WriteLine(user.Name + ": " + user.Age + " years old");
>

public static int CompareUsers(User user1, User user2)
return user1.Age.CompareTo(user2.Age);
>
>

public class User
public string Name < get; set; >
public int Age < get; set; >
>
>

Это добавило довольно много кода в наш пример, но на самом деле это не слишком сложно. Если мы начнем снизу, я создал очень простой класс пользователя, состоящее из имени и возраста. В середине я объявил метод с именем CompareUsers () — он принимает двух пользователей в качестве параметров, а затем возвращает целое число, которое будет указывать, является ли один элемент «меньшим», «тем же» или «большим» (-1, 0 или 1). Эти значения будут использоваться методом Sort() для перемещения элементов таким образом, чтобы порядок элементов соответствовал тому, что мы хотим. В этом случае я просто использую свойство Age для сравнения, оставляя нам список пользователей, отсортированных по их возрасту.

Резюме

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

Список list в C++: полный материал

обложка статьи

Всем привет! Не давно мы прошли вектор в C++, поэтому сегодня мы решили снова затронуть тему контейнеров и подготовили материал об еще одном контейнере — list.

Что такое список list

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

На картинке ниже показана, как это устроено:

как работает list в C++

У двусвязного списка нет индексов, но вместо их в C++ есть итераторы.

i_am_list[2] = 8; // ошибка!

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

пример добавления элемента в контейнер list лист

пример добавления элемента в контейнер list

На примере выше в начале было два элемента, потом мы решили добавить один элемент между ними.

пример удаление элемента из списка list

пример удаление элемента из списка list

А так совершается удаление.

Как создать список list

Сначала подключаем библиотеку — .

#include 

Далее используем конструкцию ниже:

list  тип данных > имя контейнера>;
  • < тип данных >— сюда мы должны указать тип, который хотим использовать.
  • — это будет нашим именем контейнера. Лучше указывать такое имя, которое будет говорить, за что этот контейнер отвечает.

Вот пример создания списка с типом string :

list string> listok;

Как добавить элементы при создании списка

Чтобы сразу после создания списка присвоить ему значения нужно сделать так:

list int> this_list = 4, 6, 3, 2>;

Такой способ можно использовать только в C++ 11 и выше.

Методы списка list

Вот функции которые можно применять в своей программе вместе со списком (нажмите на их имена чтобы перейти на страницу с полным руководством):

pop_front: удалить элемент в начале pop_back: удалить элемент в конце push_front: добавить элемент в начала push_back: добавить элемент в конец front: обратится к первому элементу back: обратиться к последнему элементу insert: добавить элемент в какое-то место copy: вывести все элементы списка (и не только): unique: удалить все дубликаты merge: добавление другого списка

Давайте с несколькими методами познакомимся подробнее.

С помощью его можно добавить новый элемент в любую часть контейнера (в нашем случае для списка). Вот как он работает:

insert (позиция>, значение>);

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *