Come rimuovere l'elemento dall'elenco in C #?


192

Ho un elenco memorizzato nella lista dei risultati come segue:

var resultlist = results.ToList();

Sembra qualcosa del genere:

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

Come rimuovo l'ID 2 dall'elenco?

Risposte:


368

List<T> ha due metodi che puoi usare.

RemoveAt (int index) può essere utilizzato se si conosce l'indice dell'elemento. Per esempio:

resultlist.RemoveAt(1);

Oppure puoi usare Rimuovi (oggetto T) :

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

Quando non sei sicuro che l'articolo esista davvero, puoi usare SingleOrDefault . SingleOrDefaultritornerà nullse non ci sono oggetti ( Singlegenererà un'eccezione quando non riesce a trovare l'oggetto). Entrambi lanceranno quando c'è un valore duplicato (due oggetti con lo stesso id).

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

5
bene, forsevar itemsToRemove = resultlist.Where(r => r.Id == 2); foreach (var itemToRemove in ItemsToRemove) resultList.Remove(itemToRemove);
Vlad

1
Non dovrebbe essere resultlist.Items.RemoveAt(1);?
DreamTeK,

50

Risposta breve:
Rimuovi (dall'elenco results)

results.RemoveAll(r => r.ID == 2);rimuoverà l'elemento con ID 2 in posizione results(sul posto).

Filtro (senza rimuovere dall'elenco originale results):

var filtered = result.Where(f => f.ID != 2);restituisce tutti gli articoli tranne quello con ID 2

Risposta dettagliata:

Penso che .RemoveAll()sia molto flessibile, perché puoi avere un elenco di ID oggetto che vuoi rimuovere - ti preghiamo di considerare il seguente esempio.

Se hai:

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

e assegnato alcuni valori resultscome segue:

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

Quindi è possibile definire un elenco di ID da rimuovere:

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

E semplicemente usa questo per rimuoverli:

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

Sarà rimuovere gli elementi 2 e 3 e mantenere gli articoli 1 e 4 - come specificato dal removeList. Si noti che ciò accade sul posto, quindi non è necessario alcun supporto aggiuntivo.

Naturalmente, puoi anche usarlo su singoli elementi come:

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

dove rimuoverà Bill con ID 4 nel nostro esempio.


DotNetFiddle: esegui la demo


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

C'è un piccolo aiutante di Linq che mi piace che è facile da implementare e può rendere le query con condizioni "dove non" un po 'più facili da leggere:

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
Un altro approccio simile (che usa un predicato) è usare List.FindIndex/ List.RemoteAt(che ha la caratteristica "simpatica" o "non così bella" di essere un'operazione mutante).

Vero, ma fai attenzione a dire che l'operazione di List sta mutando. Elenco utilizza un array dietro le quinte e può ricreare il suo array con una capacità sempre più piccola quando ritiene necessario. Di solito , la rimozione è una mutazione sul posto dell'array esistente.
KeithS

Questo non è thread-safe, e per la sua semplicità puoi semplicemente usare SingleOrDefault, non è necessario che sia contenuto in un metodo statico

Nessuno ha detto che fosse thread-safe (e se dipende da cosa i thread dovrebbero fare; in effetti potrebbe essere preferibile dare un diverso costrutto in memoria a un thread di lavoro piuttosto che lasciarli tutti lavorare su una raccolta simultanea ) e l'OP vuole tutti i record tranne quello corrispondente al predicato, quindi SingleOrDefault restituirebbe esattamente ciò che non vogliono. Il "metodo statico" è in realtà un metodo di estensione, come la maggior parte di Linq, e funziona ogni volta che ciò che non si desidera (uno o più elementi) è più facile da definire di quello che si fa.
KeithS

5

C'è un altro approccio. Usa List.FindIndexe List.RemoveAt.

Mentre probabilmente userei la soluzione presentata da KeithS (solo il semplice Where/ ToList) questo approccio differisce in quanto muta l'oggetto elenco originale. Questa può essere una "caratteristica" buona (o cattiva) a seconda delle aspettative.

In ogni caso, il FindIndex(accoppiato con una protezione) garantisce RemoveAtche sarà corretto se ci sono lacune negli ID o l'ordinamento è sbagliato, ecc. E l'uso RemoveAt(vs Remove) evita una seconda ricerca O (n) nell'elenco.

Ecco uno snippet 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

Buona codifica.


4

Non si specifica quale tipo di elenco, ma l'elenco generico può utilizzare il RemoveAt(index)metodo o il Remove(obj)metodo:

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

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

4

Più semplificato:

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

non è necessario creare un nuovo oggetto var.


0

... o solo resultlist.RemoveAt(1)se conosci esattamente l'indice.


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

        }

    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.