Entfernen Sie das Element basierend auf der Bedingung aus der Liste


77

Ich habe eine Struktur wie diese:

public struct stuff
{
    public int ID;
    public int quan;
}

und möchte das Produkt entfernen, wo IDist 1.
Ich versuche dies derzeit:

prods.Remove(new stuff{ prodID = 1});

und es funktioniert nicht.

DANK AN ALLE

Antworten:


64

Verwenden von linq:

prods.Remove( prods.Single( s => s.ID == 1 ) );

Vielleicht möchten Sie sogar verwenden SingleOrDefault()und prüfen, ob das Element überhaupt vorhanden ist ...

EDIT:
Da stuffes sich um eine Struktur handelt, SingleOrDefault()wird nicht null zurückgegeben. Es wird jedoch default (stuff) zurückgegeben , das eine ID von 0 hat. Wenn Sie für Ihre normalen stuff-Objekte keine ID von 0 haben, können Sie diese ID abfragen:

var stuffToRemove = prods.SingleOrDefault( s => s.ID == 1 )
if( stuffToRemove.ID != 0 )
{
    prods.Remove( stuffToRemove );
}

Ziemlich sicher, dass Remove (null) eine Ausnahme auslöst, die SingleOrDefault dort ausschließt, wo es sich befindet.
Matt Mitchell

1
@ Graphain: Ich habe ein Beispiel für Sie hinzugefügt
Tanascius

Oder vielleicht besser lesbar if (stuffToRemove != default(stuff)).
Rufus L

207

Wenn Ihr Sammlungstyp a ist List<stuff>, ist der beste Ansatz wahrscheinlich der folgende:

prods.RemoveAll(s => s.ID == 1)

Dies führt nur einen Durchgang (Iteration) über die Liste durch und sollte daher effizienter sein als andere Methoden.

Wenn Ihr Typ allgemeiner ist ICollection<T>, kann es hilfreich sein, eine kurze Erweiterungsmethode zu schreiben, wenn Sie Wert auf Leistung legen. Wenn nicht, würden Sie wahrscheinlich mit LINQ (Anruf Whereoder Single) davonkommen .


5
Diese Antwort kann nicht akzeptiert werden, da IList nicht über RemoveAll verfügt. Der Themenstarter gibt nicht an, was er / sie hat: Liste <T> oder IList <T>.
Evgeni Nabokov

5
"Kann nicht"? Haha. Sei nicht pedantisch. Selbst wenn der Autor mit einer IList arbeitet, ist die Implementierung von RemoveAll ziemlich trivial.
Noldorin

5

Wenn Sie LINQ haben:

var itemtoremove = prods.Where(item => item.ID == 1).First();
prods.Remove(itemtoremove)

Sie können Ihre whereAbfrage als Parameter zu First ()
Matt Mitchell

Oder Sie können einfach ersetzen WheremitFirst
Rufus L

3
prods.Remove(prods.Find(x => x.ID == 1));

0

prods.Remove(prods.Single(p=>p.ID == 1));

Sie können die Sammlung in foreach nicht ändern, wie Vincent vorschlägt


Single wäre langsamer als zuerst, aber es garantiert, dass Sie keine doppelten Produkte für dieselbe ID haben, nach denen Sie möglicherweise suchen möchten.
Matt Mitchell

0

Sie können nur etwas entfernen, auf das Sie einen Verweis haben. Sie müssen also die gesamte Liste durchsuchen:

stuff r;
foreach(stuff s in prods) {
  if(s.ID == 1) {
      r = s;
      break;
  }
}
prods.Remove(r);

oder

for(int i = 0; i < prods.Length; i++) {
    if(prods[i].ID == 1) {
        prods.RemoveAt(i);
        break;
    }
}

Ist es nicht schneller, die Funktion find oder findIndex für eine Liste zu verwenden, als sie zu durchlaufen?
Rob

1
Sie können die Sammlung, die Sie iterieren, nicht ändern
Matt Mitchell

@Rob, für eine Liste sollte find gleich sein.
Matt Mitchell

@ Graphain oops. @Rob, ja ein Fund ist wahrscheinlich besser.
Vincent McNabb

0

Hier ist eine Lösung für diejenigen, die sie mit Entity Framework aus der Datenbank entfernen möchten :

prods.RemoveWhere(s => s.ID == 1);

Und die Erweiterungsmethode selbst:

using System;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore;

namespace LivaNova.NGPDM.Client.Services.Data.Extensions
{
    public static class DbSetExtensions
    {
        public static void RemoveWhere<TEntity>(this DbSet<TEntity> entities, Expression<Func<TEntity, bool>> predicate) where TEntity : class
        {
            var records = entities
                .Where(predicate)
                .ToList();
            if (records.Count > 0)
                entities.RemoveRange(records);
        }
    }
}

PS Dies simuliert die Methode RemoveAll(), die für DB-Sets des Entity Frameworks nicht verfügbar ist.


-2

Sie könnten Linq verwenden.

var prod = from p in prods
           where p.ID != 1
           select p;

Dadurch wird das Objekt nicht entfernt. Wenn Sie zuweisen, als wären prods = prods.Where(p != 1).ToList()Sie näher dran, ändert dies jedoch nichts an einer Liste, die Sie als Parameter erhalten haben.
Matt Mitchell
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.