Как удалить элемент из списка в C #?


192

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

var resultlist = results.ToList();

Это выглядит примерно так:

ID FirstName  LastName
-- ---------  --------
1  Bill       Smith
2  John       Wilson
3  Doug       Berg

Как удалить идентификатор 2 из списка?

Ответы:


368

List<T> есть два метода, которые вы можете использовать.

RemoveAt (int index) можно использовать, если вы знаете индекс элемента. Например:

resultlist.RemoveAt(1);

Или вы можете использовать Remove (T item) :

var itemToRemove = resultlist.Single(r => r.Id == 2);
resultList.Remove(itemToRemove);

Если вы не уверены, что элемент действительно существует, вы можете использовать SingleOrDefault . SingleOrDefaultвернется, nullесли предмета нет ( Singleвыдаст исключение, когда не сможет найти предмет). Оба будут выбрасывать при наличии дублированного значения (два элемента с одинаковым id).

var itemToRemove = resultlist.SingleOrDefault(r => r.Id == 2);
if (itemToRemove != null)
    resultList.Remove(itemToRemove);

5
хорошо, чем возможноvar itemsToRemove = resultlist.Where(r => r.Id == 2); foreach (var itemToRemove in ItemsToRemove) resultList.Remove(itemToRemove);
Влад

1
Не должно ли это быть resultlist.Items.RemoveAt(1);?
DreamTeK

50

Краткий ответ:
Удалить (из списка results)

results.RemoveAll(r => r.ID == 2);удалит элемент с ID 2 внутри results(на месте).

Фильтр (без удаления из исходного списка results):

var filtered = result.Where(f => f.ID != 2);возвращает все элементы, кроме одного с идентификатором 2

Подробный ответ:

Я думаю, что .RemoveAll()это очень гибко, потому что вы можете иметь список идентификаторов элементов, которые вы хотите удалить - пожалуйста, посмотрите на следующий пример.

Если у вас есть:

class myClass {
    public int ID; public string FirstName; public string LastName;
}

и присвоил некоторые значения resultsследующим образом:

var results=new List<myClass> {
    new myClass()  { ID=1, FirstName="Bill", LastName="Smith" },
    new myClass()  { ID=2, FirstName="John", LastName="Wilson" },
    new myClass()  { ID=3, FirstName="Doug", LastName="Berg" },
    new myClass()  { ID=4, FirstName="Bill", LastName="Wilson" },
};

Затем вы можете определить список идентификаторов для удаления:

var removeList = new List<int>() { 2, 3 };

И просто используйте это, чтобы удалить их:

results.RemoveAll(r => removeList.Any(a => a==r.ID));

Он удалит элементы 2 и 3 и сохранит элементы 1 и 4, как указано в removeList. Обратите внимание, что это происходит на месте, поэтому никаких дополнительных назначений не требуется.

Конечно, вы также можете использовать его для отдельных предметов, таких как:

results.RemoveAll(r => r.ID==4);

где он удалит Билл с ID 4 в нашем примере.


DotNetFiddle: запустить демо


45
resultList = results.Where(x=>x.Id != 2).ToList();

Есть небольшой помощник Linq, который мне нравится, его легко реализовать, и он может немного облегчить чтение запросов с условиями «где нет»:

public static IEnumerable<T> ExceptWhere<T>(this IEnumerable<T> source, Predicate<T> predicate)
{
    return source.Where(x=>!predicate(x));
}

//usage in above situation
resultList = results.ExceptWhere(x=>x.Id == 2).ToList();

1
Другой похожий подход (использующий предикат) заключается в использовании List.FindIndex/ List.RemoteAt(который имеет «приятную» или «не очень приятную» функцию мутации).

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

Это не потокобезопасно, и для его простоты вы можете просто использовать SingleOrDefault, его не нужно содержать в статическом методе

Никто не сказал, что это потокобезопасно (и зависит ли это от того, что потоки должны делать; фактически, может быть предпочтительнее дать рабочему потоку другую конструкцию в памяти, чем позволить всем им работать в одной параллельной коллекции). ), и OP хочет получить все записи, кроме той, которая соответствует предикату, поэтому SingleOrDefault фактически вернул бы именно то, что им не нужно. «Статический метод» на самом деле является методом расширения, как и большинство Linq, и он работает всякий раз, когда то, что вам не нужно (один или несколько элементов), легче определить, чем то, что вы делаете.
KeithS

5

Есть другой подход. Он использует List.FindIndexи List.RemoveAt.

Хотя я, вероятно, использовал бы решение, представленное KeithS (просто Where/ ToList), этот подход отличается тем, что он мутирует исходный объект списка. Это может быть хорошей (или плохой) «функцией» в зависимости от ожиданий.

В любом случае, FindIndex(в сочетании с защитой) гарантирует, что RemoveAtбудет правильно, если в идентификаторах есть пробелы или неправильный порядок и т. Д., И использование RemoveAt(vs Remove) позволяет избежать повторного поиска O (n) по списку.

Вот фрагмент кода LINQPad:

var list = new List<int> { 1, 3, 2 };
var index = list.FindIndex(i => i == 2); // like Where/Single
if (index >= 0) {   // ensure item found
    list.RemoveAt(index);
}
list.Dump();        // results -> 1, 3

Удачного кодирования.


4

Вы не указываете, какой тип списка, но общий список может использовать либо RemoveAt(index)метод, либо Remove(obj)метод:

// Remove(obj)
var item = resultList.Single(x => x.Id == 2);
resultList.Remove(item);

// RemoveAt(index)
resultList.RemoveAt(1);


0

... или просто resultlist.RemoveAt(1)если вы точно знаете индекс.


0
{
    class Program
    {
        public static List<Product> list;
        static void Main(string[] args)
        {

            list = new List<Product>() { new Product() { ProductId=1, Name="Nike 12N0",Brand="Nike",Price=12000,Quantity=50},
                 new Product() { ProductId =2, Name = "Puma 560K", Brand = "Puma", Price = 120000, Quantity = 55 },
                 new Product() { ProductId=3, Name="WoodLand V2",Brand="WoodLand",Price=21020,Quantity=25},
                 new Product() { ProductId=4, Name="Adidas S52",Brand="Adidas",Price=20000,Quantity=35},
                 new Product() { ProductId=5, Name="Rebook SPEED2O",Brand="Rebook",Price=1200,Quantity=15}};


            Console.WriteLine("Enter ProductID to remove");
            int uno = Convert.ToInt32(Console.ReadLine());
            var itemToRemove = list.Find(r => r.ProductId == uno);
            if (itemToRemove != null)
                list.Remove(itemToRemove);
            Console.WriteLine($"{itemToRemove.ProductId}{itemToRemove.Name}{itemToRemove.Brand}{itemToRemove.Price}{ itemToRemove.Quantity}");
            Console.WriteLine("------------sucessfully Removed---------------");

            var query2 = from x in list select x;
            foreach (var item in query2)
            {
                /*Console.WriteLine(item.ProductId+" "+item.Name+" "+item.Brand+" "+item.Price+" "+item.Quantity );*/
                Console.WriteLine($"{item.ProductId}{item.Name}{item.Brand}{item.Price}{ item.Quantity}");
            }

        }

    }
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.