Jak usunąć element z listy w C #?

190

Mam listę zapisaną na liście wyników w następujący sposób:

var resultlist = results.ToList();

Wygląda to mniej więcej tak:

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

Jak usunąć ID 2 z listy?

Nate Pet
źródło

Odpowiedzi:

367

List<T> ma dwie metody, których możesz użyć.

RemoveAt (int index) może być użyty, jeśli znasz indeks elementu. Na przykład:

resultlist.RemoveAt(1);

Lub możesz użyć Usuń (element T) :

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

Jeśli nie masz pewności, czy element naprawdę istnieje, możesz użyć funkcji SingleOrDefault . SingleOrDefaultzwróci, nulljeśli nie ma przedmiotu ( Singlezgłasza wyjątek, gdy nie może znaleźć przedmiotu). Oba będą rzucać, gdy będzie zduplikowana wartość (dwa przedmioty o tej samej wartości id).

var itemToRemove = resultlist.SingleOrDefault(r => r.Id == 2);
if (itemToRemove != null)
    resultList.Remove(itemToRemove);
Wouter de Kort
źródło
5
cóż, niż możevar itemsToRemove = resultlist.Where(r => r.Id == 2); foreach (var itemToRemove in ItemsToRemove) resultList.Remove(itemToRemove);
Vlad
1
Nie powinno tak być resultlist.Items.RemoveAt(1);?
DreamTeK,
49

Krótka odpowiedź:
Usuń (z listy results)

results.RemoveAll(r => r.ID == 2);usunie przedmiot z ID 2 w results(na miejscu).

Filtruj (bez usuwania z oryginalnej listy results):

var filtered = result.Where(f => f.ID != 2);zwraca wszystkie elementy oprócz tego z ID 2

Szczegółowa odpowiedź:

Myślę, że .RemoveAll()jest bardzo elastyczny, ponieważ możesz mieć listę identyfikatorów produktów, które chcesz usunąć - zapoznaj się z poniższym przykładem.

Jeśli masz:

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

i przypisał niektóre wartości do results następujących:

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" },
};

Następnie możesz zdefiniować listę identyfikatorów do usunięcia:

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

I po prostu użyj tego, aby je usunąć:

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

Będzie usunąć pozycje 2 i 3 oraz utrzymanie pozycji 1 i 4 - w sposób określony przezremoveList . Pamiętaj, że dzieje się to na miejscu, więc nie jest wymagane dodatkowe przypisanie.

Oczywiście możesz go również używać do pojedynczych elementów, takich jak:

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

gdzie usunie to rachunek z identyfikatorem 4 w naszym przykładzie.


DotNetFiddle: Uruchom wersję demo

Matt
źródło
45
resultList = results.Where(x=>x.Id != 2).ToList();

Jest mały pomocnik Linq, który mi się podoba, który jest łatwy do wdrożenia i może ułatwić czytanie zapytań w warunkach „gdzie nie”:

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();
KeithS
źródło
1
Innym podobnym podejściem (korzystającym z predykatu) jest użycie List.FindIndex/ List.RemoteAt(które ma cechę „miłą” lub „niezbyt przyjemną” polegającą na mutacji).
To prawda, ale być ostrożnym mówiąc, że operacja lista jest to mutacja. Lista korzysta z tablicy za kulisami i może odtworzyć tablicę o mniejszej lub większej pojemności, jeśli uzna to za konieczne. Zwykle usunięcie jest mutacją w miejscu istniejącej tablicy.
KeithS
To nie jest wątek bezpieczny, a ze względu na swoją prostotę możesz po prostu użyć SingleOrDefault, nie musi być zawarty w metodzie statycznej
Nikt nie powiedział, że jest bezpieczny dla wątków (i czy zależy to od tego, co powinny robić wątki; w rzeczywistości lepiej byłoby nadać innej konstrukcji w pamięci wątek roboczy niż pozwolić im wszystkim pracować na jednej równoległej kolekcji ), a OP chce wszystkich rekordów oprócz tego, który pasuje do predykatu, więc SingleOrDefault zwróci dokładnie to, czego nie chce. „Metoda statyczna” jest w rzeczywistości metodą rozszerzenia, podobnie jak większość Linq, i działa, ilekroć nie chcesz (jednego lub wielu elementów) łatwiej zdefiniować niż to, co robisz.
KeithS
5

Istnieje inne podejście. Wykorzystuje List.FindIndexi List.RemoveAt.

Chociaż prawdopodobnie użyłbym rozwiązania przedstawionego przez KeithS (tylko prosty Where/ ToList), to podejście różni się tym, że mutuje oryginalny obiekt listy. Może to być dobra (lub zła) „cecha” w zależności od oczekiwań.

W każdym razie FindIndex(w połączeniu z osłoną) zapewnia RemoveAtpoprawność, jeśli w identyfikatorach występują luki lub kolejność jest nieprawidłowa itp., A użycie RemoveAt(vs Remove) pozwala uniknąć drugiego przeszukiwania listy O (n) przez listę.

Oto fragment kodu 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

Szczęśliwego kodowania.


źródło
4

Nie określasz, jaki rodzaj listy, ale ogólna lista może używać albo RemoveAt(index)metody, albo Remove(obj)metody:

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

// RemoveAt(index)
resultList.RemoveAt(1);
mgnoonan
źródło
4

Bardziej uproszczone:

resultList.Remove(resultList.Single(x => x.Id == 2));

nie ma potrzeby tworzenia nowego obiektu var.

Javier Andres Caicedo
źródło
0

... lub tylko resultlist.RemoveAt(1)jeśli znasz dokładnie indeks.

Vlad
źródło
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}");
            }

        }

    }
}
Prabhakaran M.
źródło