Comment supprimer un élément de la liste en C #?

192

J'ai une liste stockée dans la liste de résultats comme suit:

var resultlist = results.ToList();

Cela ressemble à quelque chose comme ceci:

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

Comment supprimer l'ID 2 de la liste?

Nate Pet
la source

Réponses:

368

List<T> a deux méthodes que vous pouvez utiliser.

RemoveAt (index int) peut être utilisé si vous connaissez l'index de l'élément. Par exemple:

resultlist.RemoveAt(1);

Ou vous pouvez utiliser Supprimer (élément T) :

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

Lorsque vous n'êtes pas sûr que l'élément existe vraiment, vous pouvez utiliser SingleOrDefault . SingleOrDefaultretournera nulls'il n'y a pas d'élément ( Singlelèvera une exception quand il ne peut pas trouver l'élément). Les deux seront lancés lorsqu'il y a une valeur en double (deux éléments avec le même id).

var itemToRemove = resultlist.SingleOrDefault(r => r.Id == 2);
if (itemToRemove != null)
    resultList.Remove(itemToRemove);
Wouter de Kort
la source
5
bien, que peutvar itemsToRemove = resultlist.Where(r => r.Id == 2); foreach (var itemToRemove in ItemsToRemove) resultList.Remove(itemToRemove);
Vlad
1
Cela ne devrait-il pas être resultlist.Items.RemoveAt(1);?
DreamTeK
50

Réponse courte:
Supprimer (de la liste results)

results.RemoveAll(r => r.ID == 2);supprimera l'élément avec ID 2 en results(en place).

Filtre (sans supprimer de la liste d'origine results):

var filtered = result.Where(f => f.ID != 2);renvoie tous les éléments sauf celui avec l' ID 2

Réponse détaillée:

Je pense que .RemoveAll()c'est très flexible, car vous pouvez avoir une liste d'identifiants d'articles que vous souhaitez supprimer - veuillez prendre en compte l'exemple suivant.

Si tu as:

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

et assigné quelques valeurs resultscomme suit:

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

Ensuite, vous pouvez définir une liste d'identifiants à supprimer:

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

Et utilisez simplement ceci pour les supprimer:

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

Il supprimera les éléments 2 et 3 et conservera les éléments 1 et 4 - comme spécifié par le removeList. Notez que cela se produit en place, donc aucune attribution supplémentaire n'est requise.

Bien sûr, vous pouvez également l'utiliser sur des éléments uniques tels que:

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

où il supprimera Bill avec l'ID 4 dans notre exemple.


DotNetFiddle: lancez la démo

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

Il y a un petit assistant Linq que j'aime, qui est facile à implémenter et qui peut rendre les requêtes avec des conditions "where not" un peu plus faciles à lire:

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
la source
1
Une autre approche similaire (qui utilise un prédicat) consiste à utiliser List.FindIndex/ List.RemoteAt(qui a la fonctionnalité "sympa" ou "pas si agréable" d'être une opération de mutation).
Certes, mais soyez prudent de dire que l'opération de liste est de muter. List utilise un tableau dans les coulisses, et il peut recréer son tableau avec une capacité plus petite ou plus grande quand il le juge nécessaire. En général , la suppression est une mutation sur place du tableau existant.
KeithS
Ce n'est pas thread-safe, et pour sa simplicité, vous pouvez simplement utiliser SingleOrDefault, il n'a pas besoin d'être contenu dans une méthode statique
Personne n'a dit qu'il était thread-safe (et si cela dépend de ce que les threads sont censés faire; il peut en fait être préférable de donner une construction en mémoire différente à un thread de travail plutôt que de les laisser tous travailler sur une collection simultanée ), et l'OP veut tous les enregistrements sauf celui correspondant au prédicat, donc SingleOrDefault renverrait en fait exactement ce qu'ils ne veulent pas . La "méthode statique" est en fait une méthode d'extension, comme la plupart des Linq, et elle fonctionne chaque fois que ce que vous ne voulez pas (un élément ou plusieurs) est plus facile à définir que ce que vous faites.
KeithS
5

Il existe une autre approche. Il utilise List.FindIndexet List.RemoveAt.

Alors que j'utiliserais probablement la solution présentée par KeithS (juste le simple Where/ ToList), cette approche diffère en ce qu'elle mute l'objet de liste d'origine. Cela peut être une bonne (ou une mauvaise) «fonctionnalité» en fonction des attentes.

Dans tous les cas, le FindIndex(couplé à une garde) garantit que le RemoveAtsera correct s'il y a des lacunes dans les identifiants ou si l'ordre est incorrect, etc., et l'utilisation de RemoveAt(vs Remove) évite une deuxième recherche O (n) dans la liste.

Voici un extrait de 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

Bon codage.


la source
4

Vous ne spécifiez pas le type de liste, mais la liste générique peut utiliser soit la RemoveAt(index)méthode, soit la Remove(obj)méthode:

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

// RemoveAt(index)
resultList.RemoveAt(1);
mgnoonan
la source
4

Plus simplifié:

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

il n'est pas nécessaire de créer un nouvel objet var.

Javier Andres Caicedo
la source
0

... ou simplement resultlist.RemoveAt(1)si vous connaissez exactement l'index.

Vlad
la source
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
la source