2016-04-16 2 views
1

Ich möchte ein Element aus einer Liste basierend auf einer Bedingung entfernen. Das Problem ist, dass ich es nicht entfernen kann, während ich es vorwärts durchführe, da sein Array wie die Implementierung ist, und das ändert Listing-Struktur und Anzahl.C# Entfernen von Elementen beim Durchlaufen der Liste - Rückwärts iterieren oder i- oder linq verwenden, um gleichzeitig zu iterieren und zu entfernen?

Also las ich dies beantwortet, und ich war überzeugt, dass dies die Lösung sein sollte: how-to-remove-elements-from-a-generic-list-while-iterating-over-it

Aber jemand hat mir Feedback, dass dies nicht leicht verständlich ist, da wir es rückwärts iterieren, vielmehr sollten wir wiederholen vorwärts und tun i- wann immer die Entfernungsbedingung erfüllt ist.

var list = new List<int>(Enumerable.Range(1, 10)); 
for (int i = 0; i < list.Count; i++) 
{ 
    if (list[i] > 5) 
    { 
     list.RemoveAt(i); 
     i--; 
    } 
} 
list.ForEach(i => Console.WriteLine(i)); 

I-Einheit getestet diesen Ansatz und die Ergebnisse sind wie erwartet, aber ich bin immer noch besorgt, dass es für alle möglichen Fälle gleich sein würde, da ich diese Antwort bekam nirgends in jedem Forum und jeder hatte vorgeschlagen, rückwärts zu durchlaufen.

Kann mir bitte jemand sagen, ob sich beide Lösungen gleich verhalten oder anders sind?

+0

Warum Sie nicht mögen [ 'Liste .RemoveAll'] (https://msdn.microsoft.com/en-us/library/wdka673a.aspx)? –

Antwort

2

Die bevorzugte Art und Weise Elemente aus einer Liste zu entfernen, an Ort und Stelle, ist es mit dieser Art von Code in umgekehrter Reihenfolge zu tun:

int index = list.Count - 1; 
while (index >= 0) 
{ 
    if (expression identifying item to remove) 
     list.RemoveAt(index); 
    else 
     index--; 
} 

Nun, denken Sie daran, dass dies in einen der Entfernung gilt nur Liste in-place, was bedeutet, dass Sie keine neue Liste der Elemente erstellen möchten, die Sie behalten möchten. Wenn Sie das tun können, erstellen Sie eine neue Liste mit den zu behaltenden Elementen, ein LINQ-Ausdruck ist wahrscheinlich besser.

Also, warum ist der obige Ansatz bevorzugt?

Nun, bedenken Sie dies. Was bedeutet "einen Gegenstand von einer Liste entfernen" überhaupt? Die zugrunde liegende Datenstruktur eines List<T> in C# ist ein Array. Das Entfernen eines Elements aus einem Array kann nicht wirklich durchgeführt werden, aber Sie können die Werte innerhalb eines Arrays verschieben. Um ein Objekt aus einem Array zu "entfernen", können Sie alle darauffolgenden Elemente um einen Index nach oben verschieben.

Dies ist ein Vorgang, der relativ zur Anzahl der darauf folgenden Elemente Zeit benötigt.

Schauen wir uns dies im "Vorwärts-Ansatz" an. Bei diesem Ansatz würden Sie bei Index 0 beginnen und jedes Mal nach oben gehen, wenn Sie einen Gegenstand zum Aufbewahren finden, aber Sie würden auch einen Gegenstand entfernen, indem Sie jeden Gegenstand, der ihm folgt, um ein Element nach unten verschieben.

Lassen Sie uns ein einfaches Beispiel machen, Sie haben eine Liste von jeder Zahl von 1 bis 10, und Sie möchten jeden geraden Elementwert entfernen (2, 4, 6, 8, etc.).

So haben Sie diese:

1 2 3 4 5 6 7 8 9 10 

Das erste Element ist 2 zu entfernen, das jede Zahl zu bewegen haben wird, die es folgt, 3 bis 10, einen Index nach unten.Das sind 8 gezogene Zahlen.

Der nächste Artikel ist 4, muss es 5 bis 10 nach unten bewegen, die 6 Zahlen ist. Jetzt haben wir insgesamt 14 Nummern bewegt.

Als nächstes ist 6, gehe 7 bis 10 runter, das sind 4 Zahlen, jetzt sind wir bis zu 18 Nummern bewegt.

Nächste ist 8, bewegen 9 und 10, 2 Zahlen, wir sind bis zu 20 Nummern bewegt.

Da dem letzten, den wir entfernen möchten, keine 10 folgen, haben wir insgesamt 20 Nummern verschoben.

Jetzt machen wir es in umgekehrter Reihenfolge.

Zuerst schauen wir auf 10, wir wollen das entfernen, keine Zahlen folgen, also keine Bewegung.

Als nächstes wollen wir 8 entfernen, es folgt nur noch eine Zahl, also bewegen wir 9 eine Kerbe nach unten. 10 wurde bereits entfernt, so dass es nicht mehr vorhanden ist.

Als nächstes möchten wir 6 entfernen. Es folgen zwei Zahlen, 7 und 9, also bewegen Sie diese nach unten, insgesamt 3 Zahlen.

Entfernen Sie 4, folgen Sie 5, 7 und 9, also haben wir jetzt 6 Zahlen verschoben.

Entfernen 2 - 3, 5, 7 und 9 folgt es so jetzt haben wir 10 Zahlen insgesamt verschoben.

Also, wenn es um eine Liste geht, hängt es ganz davon ab, was Sie meinen "verhält sich auf die gleiche Weise".

Wird das Endergebnis gleich sein, wenn wir nur in Betracht ziehen, welche Zahlen in der endgültigen Liste verbleiben?

Ja.

Ist die Gesamtlaufzeit gleich?

Nr

0

Ich würde vorschlagen, nicht nur den Index verwenden, um die Elemente aus der Liste innerhalb der Iteration zu entfernen. Verwenden Sie einfach den Linq Select with where-Zustand. Dies wird Ihnen tatsächlich eine neue Liste ergeben.

var list = new List<int>(Enumerable.Range(1, 10)); 
var newList= list.Select(number=>number<=5).ToList(); 

Und jetzt wird die newList nur die Elemente enthalten, die die Bedingung erfüllt, die Sie in Lambda-Ausdruck angeben.

+0

, aber die ausgewählten Elemente wurden nicht aus der ursprünglichen Liste entfernt. Ich muss sie entfernen und die Liste mit subtrahierten Elementen woanders verwenden. – maverick

+0

okay, wenn ich Ihr Problem richtig verstehe, werden Sie die Liste nach dem Entfernen einiger Elemente basierend auf einer Bedingung verwenden. So wie es mein vorstehender Code tut. Es löscht nichts aus der ursprünglichen Liste. Es wird nur eine neue Liste für Sie erstellen, nachdem Sie die Elemente aus den ursprünglichen Ergebnissen mit Ihrer Bedingung gefiltert haben. Sie können die neue Liste woanders verwenden. –

Verwandte Themen