Frage

    

Diese Frage bereits eine Antwort hier:

         

Duplizieren

Ändern einer Sammlung Während Iterieren Through It


Hat jemand ein schönes Muster, mich zu erlauben um die Unfähigkeit zu erhalten Objekte zu entfernen, während ich Schleife durch eine zählbare Sammlung (zB ein IList oder KeyValuePairs in einem Wörterbuch)

Zum Beispiel schlägt die folgende, wie es die Liste ändert während des foreach aufgezählt über werden

foreach (MyObject myObject in MyListOfMyObjects)
{
     if (condition) MyListOfMyObjects.Remove(myObject);
}

In der Vergangenheit habe ich zwei Methoden verwendet.

Ich habe die foreach mit einem for-Schleife (um nicht zu ändern, um die alle Indizes ich über bin Looping, wenn ich ein Objekt entfernen) umgekehrt ersetzt werden.

I habe auch versucht, eine neue Sammlung von Objekten, Speicherung in einer Schleife zu entfernen, dann durch diese Sammlung Looping und die Objekte aus der ursprünglichen Sammlung entfernt.

Diese funktionieren gut, aber weder fühlt nett, und ich habe mich gefragt, ob jemand mit einem gekommen ist mehr elegant Lösung für das Problem

War es hilfreich?

Lösung

Es gibt eine nützliche List<T>.RemoveAll(Predicate<T> match) Methode, die ich denke, ist für diese entworfen: http: / /msdn.microsoft.com/en-us/library/wdka673a.aspx

Andere Tipps

Es ist eine Art einfältig, aber wenn ich plane Elemente aus einem IEnumerable / IList löschen ich in der Regel nur eine Kopie erstellen:

foreach (MyObject myObject in new List<MyObject>(MyListOfMyObjects))
{
     if (condition) MyListOfMyObjects.Remove(myObject);
}

Es ist nicht der effizienteste Weg, es zu tun, aber es ist leicht zu lesen. Vorzeitige Optimierung und so weiter.

Haben die inverse, eine neue Liste zu erstellen:

List myFilteredList = new List();
foreach (MyObject myObject in myListOfMyObjects)
{
     if (!condition) myFilteredList.Add(myObject);
}

Dann die neue Liste verwenden, wo immer Sie es brauchen.

Sie können auch einen LINQ Ausdruck leicht verwenden, wieder inversing die Bedingung. Dies hat den zusätzlichen Vorteil, dass nicht eine neue Struktur zu schaffen, sondern auch die Tücken wobei ein fauler enumerable:

var myFilteredList = from myObject in myListOfMyObjects
                     where !condition
                     select myObject;

Wenn Sie jedoch wirklich die Elemente aus der Liste entfernen müssen, ich verwende in der Regel den „eine neue Liste erstellen, dann wiederholen und entfernen“ -Ansatz.

Ich kam in diesem Beitrag und dachte, ich würde teilen.

void RemoveAll(object condition)  
{

    bool found = false;

    foreach(object thisObject in objects)    
    {

        if (condition)    
        {    
            objects.Remove(thisObject);

            found = true;

            break; //exit loop    
        }     
     }

    // Call again recursively

    if (found) RemoveAll(condition);

}

Ich mag nicht die for-Schleife Idee umgekehrt, denn das funktioniert nur auf bestimmte Datenstrukturen.

Generell würde ich die zweite Technik verwenden und reichern sich die Elemente in einem separaten gelöscht werden ‚to-Lösch‘ Sammlung. Wenn Löschung kann bestehende Iterierten verursacht ungültig zu machen (wie bei jeder ausgewogenen Baum Sammlung zum Beispiel passieren wird), dann sehe ich nicht einen Weg, um diesen.

Die einzige andere Technik, die ich gelegentlich verwendet habe, ist die gesamte Iteration neu zu starten, wenn Sie das erste Element löschen finden. Wenn Sie machen es alle Elemente, ohne finden durch löschen dann wird die Funktion beendet. Dies ist ineffizient, aber manchmal notwendig, wenn aus der Sammlung ein Element löschen kann den Satz von Positionen ändern, die gelöscht werden müssen.

Ich habe ein Wörterbuch und möchten alle Werte entsorgen. Wenn jeder Wert angeordnet ist, entfernt er sich aus dem Wörterbuch, die das Problem diskutieren Sie erstellt. Ich habe folgende Möglichkeiten:

foreach (var o in dictionary.Values.ToList())
{
  o.Dispose();
}

Ich schätze dies jetzt tot sein kann, aber die Art, wie ich das immer tun ist:

foreach (MyObject myObject in MyListOfMyObjects)
{

if (Bedingung) MyListOfMyObjects.Remove (myObject);

break;

}

Objekt wird entfernt und dann Schleife beendet, Viola!

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top