Frage

Ich habe einen Dritten api, die eine Klasse hat, dass Gibt einen Enumerator für verschiedene Elemente in der Klasse.

Ich brauche ein Element in diesem enumerator zu entfernen, so kann ich nicht „für jeden“ verwenden. Option Nur ich denken kann, ist die Zählung zu erhalten, indem über die ENUM Iterieren und dann ein normales for-Schleife laufen, um die Elemente zu entfernen.

Wer weiß einen Weg, die zwei Schleifen zu vermeiden?

Danke

[Update] entschuldigen uns für die Verwirrung, aber Andrey unten in den Kommentaren richtig ist.

Hier finden Sie einige Pseudo-Code aus meinem Kopf, die nicht funktionieren, und für die ich eine Lösung suchen, die zwei Schleifen nicht beinhalten wird, aber ich denke, es ist nicht möglich:

for each (myProperty in MyProperty)
{
if (checking some criteria here)
   MyProperty.Remove(myProperty)
}

MyProperty ist die Dritte-Klasse, die Geräte des Enumerator und das Entfernen Methode.

War es hilfreich?

Lösung

Gemeinsames Muster ist so etwas wie dies zu tun:

List<Item> forDeletion = new List<Item>();

foreach (Item i in somelist)
   if (condition for deletion) forDeletion.Add(i);

foreach (Item i in forDeletion)
   somelist.Remove(i); //or how do you delete items 

Andere Tipps

Schleife durch sie einmal und ein zweites Array erstellen, welche die Elemente enthält, die gelöscht werden soll nicht.

Wenn Sie es ist eine Sammlung kennen, können Sie mit rückgängig gemacht für gehen:

for (int i = items.Count - 1; i >= 0; i--)
{
   items.RemoveAt(i);
}

Ansonsten Sie haben zwei Schleifen zu tun.

Sie können so etwas wie dies erstellen:

      public IEnumerable<item> GetMyList()
    {
        foreach (var x in thirdParty )
        {
            if (x == ignore)
                continue;
            yield return x;
        }

    }
  

Ich brauche ein Element in diesem enumerator

entfernen

Solange dies ein einzelnes Element ist das kein Problem. Die Regel ist, dass Sie nicht weiter Iterierte nach der Sammlung zu ändern. Also:

foreach (var item in collection) {
    if (item.Equals(toRemove) {
        collection.Remove(toRemove);
        break;      // <== stop iterating!!
    }
}

Es ist nicht möglich, ein Element aus einem Enumerator zu entfernen. Was können Sie tun, ist oder Filter zu kopieren (oder beides), um den Inhalt der gesamten Enumerationsfolge. Sie können dies erreichen, indem Linq mit und tun smth wie folgt aus:

   YourEnumerationReturningFunction().Where(item => yourRemovalCriteria);

Können Sie auf die API erarbeiten und die API-Aufrufe Sie verwenden?

Wenn Sie erhalten eine IEnumerator<T> oder IEnumerable<T> Sie keine Artikel aus der Sequenz hinter dem enumerator entfernen können, weil es keine Methode, dies zu tun. Und Sie sollten natürlich nicht darauf verlassen, unten, um eine empfangene Objekt Gießen, weil die Implementierung ändern können. (Eigentlich eine gut gestaltete API sollte nicht aussetzen veränderbare Objekte halten internen Zustand überhaupt.)

Wenn Sie erhalten IList<T> oder etwas ähnliches kann man einfach eine normale for Schleife von hinten nach vorne verwenden und die Elemente entfernen, je nach Bedarf, weil es kein Iterator ist der Zustand beschädigt werden könnte. (Hier ist die Regel über veränderbaren Zustand auszusetzen sollte wieder gelten -. Die zurückgegebene Sammlung Modifizierung sollte keinen Zustand ändern)

IEnumerator.Count () wird zur Laufzeit entscheiden, was es tun muss - enumerate zu zählen oder zu sehen zu reflektieren, um es eine Sammlung ist, und rufen .Count auf diese Weise.

Ich mag Sjoerd Vorschlag aber ich mache mir Sorgen darüber, wie viele Artikel, die wir darüber reden können.

Warum nicht so etwas wie ..

 // you don't want 2 and 3
 IEnumerable<int> fromAPI = Enumerable.Range(0, 10);
 IEnumerable<int> result = fromAPI.Except(new[] { 2, 3 });

Eine saubere, gut lesbare Art und Weise, dies zu tun ist, ergibt sich als (ich vermute, an der Dritt Container API hier, da Sie nicht angegeben haben.)

foreach(var delItem in ThirdPartyContainer.Items
                       .Where(item=>ShouldIDeleteThis(item))
                       //or: .Where(ShouldIDeleteThis)
                       .ToArray()) {
    ThirdPartyContainer.Remove(delItem);
}

Der Aufruf von .ToArray() stellt sicher, dass alle Elemente Gierig gelöscht werden zwischengespeichert wurden, bevor die foreach Iteration beginnt.

Hinter den Kulissen beinhaltet dies ein Array und eine zusätzliche Iteration über das, aber das ist in der Regel sehr billig, und der Vorteil dieser Methode gegenüber den anderen Antworten auf diese Frage ist, dass es auf Ebene enumerables funktioniert und beinhaltet nicht heikel wandelbar Zustand Probleme, die schwer zu lesen und leicht zu bekommen sind falsch.

Im Gegensatz dazu in umgekehrten laufen, während keine Raketenwissenschaft, ist viel anfälliger für Off-by-one Fehler und schwieriger zu lesen; und es stützt sich auch auf Interna der Sammlung, wie nicht in Ordnung zwischen Deletionen Ändern (z besser nicht ein binäres heap sein, sagen). Manuelles Hinzufügen von Elementen, die zu einer temporären Liste gelöscht werden sollen, sind nur unnötigen Code - das ist, was .ToArray () fein gerade tun: -).

ein Enumerator hat immer ein eigenes Feld auf die reale Sammlung zeigt.
Sie können es über reflection.modify es.
Spaß haben.

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