Hallo
Ich habe eine ArrayKlasse "Articles", in der Datensätze einer DB Abfrage gespeichert werden, unter anderem auch die articleID.
In einer 2. ArrayList habe ich eine Auflistung von ArticleIDs die aus dem "Articles" Array gelöscht werden müssen.
Wie kann ich diesen Vergleich und das Löschen der betreffenden Einträge im "Articles" Array möglichst Performance-optimiert umsetzen?
Ich versuche es mit:
foreach (Articles articles in articlesresponse.ResultList)
{
// List Inhalt ArticleID an Variable zuweisen
int articleIDNext = articles.ArticleID;
if (listdenied.Contains(articleIDNext))
{
articlesresponse.ResultList.Remove(articles);
}
}
Ich lese also die ArticleIDs aus dem "Articles" Array aus und vergleiche ob die ID in der "listdenied" ArrayList enthalten ist. Wenn ja lösche ich den betreffenden Datensatz.
Leider kann nach dem Löschen eines Eintrages die foreach - Schleife nicht fortgesetzt werden. Es erscheint der Fehler:
"System.InvalidOperationException: Die Auflistung wurde geändert. Der Enumerationsvorgang kann möglicherweise nicht ausgeführt werden."
Wie lässt sich dieser Fehler vermeiden?
Was gibt es sonst für Möglichkeiten?
Danke für eure Hilfe
Hallo canuck,
Leider kann nach dem Löschen eines Eintrages die foreach - Schleife nicht fortgesetzt werden.
ja so ist das. Wenn du die Aufzählung ändern willst, musst du for verwenden.
Die schnellste Möglichkeit wird sein, die Artikel als Keys in ein Dictionary einzutragen und die ungewollten mit Remove herauszulöschen.
herbivore
Hallo,
vielleicht klappt das:
int i = 0;
while (i<response.ResultList.Length)
{
Articles a = response.ResultList[i];
if(/*remove*/)
{
response.ResultList.RemoveAt[i];
}
else
{
i++;
}
}
Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca
Hallo MarsStein,
das wage ich zu bezweifeln, da Arrays nicht dynamisch sind. Du meinst wahrscheinlich ArrayList. Da gibts das Add und Remove.
Bei Arrays kannst du höchstens einen "null"-Wert definieren.
Beispiel Element 3 von Array auf null setzen:
//Array erstellen
int[] positiveIntegers = int[10];
//Array füllen
for(int i = 0; i < positiveIntegers.Length; i++) {
positiveIntegers[i] = i+1;
}
//Element an Stelle 3 löschen
positiveIntegers[2] = -1;
//Array auslesen
for(int i = 0; i < positiveIntegers.Length; i++) {
if(positiveIntegers[i] != -1) {
Console.WriteLine("Element an Stelle "+(i+1).ToString()+" ist nicht leer.");
}
}
Es ist toll jemand zu sein, der nichts von der persönlichen Meinung Anderer hält. - frisch-live.de
Sorry, ich habe mich wohl zuwenig klar ausgedrückt.
Es sind beides ArrayLists, bei der "Articles" Liste ist zusätzlich eine Klasse dahinter die die einzelnen Listenelemente vorgibt. Habe den Titel meines Threads noch angepasst.
Es funktioniert jetzt mit:
int i = 0;
while (i<articlesresponse.ResultList.Count)
{
Articles articles = articlesresponse.ResultList[i];
int articleIDNext = articles.ArticleID;
if (listdenied.Contains(articleIDNext))
{
articlesresponse.ResultList.Remove(articles);
}
else
{
i++;
}
}
Jedenfalls löscht es mir nun die gewünschten Einträge heraus.
Ich denke, das ist der richtige Weg, oder gibt es noch einen performanteren?
Danke für die Hilfe und Gruss
@frisch
Das ist mir schon klar, aber im Beispielquelltext
Original von canuck
if (listdenied.Contains(articleIDNext))
{
articlesresponse.ResultList.Remove(articles);
}
Daher bin ich von einem Objekt ausgegangen, das die Methode unterstützt.
Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca
Evtl. eleganter ist es, die Iteration der ArrayList vom letzten Element her zu beginnen - so stellst du sicher, dass keine Elemente die noch vor dem aktuellen Iterator-Wert liegen, geändert werden.
Hallo canuck,
Ich denke, das ist der richtige Weg, oder gibt es noch einen performanteren?
ich habe ja schon den Weg genannt, den ich für am performantesten halte.
herbivore
@ dani.net
meinst du so?
int i = articlesresponse.ResultList.Count;
while (i>0)
{
Articles articles = articlesresponse.ResultList[i];
int articleIDNext = articles.ArticleID;
if (listdenied.Contains(articleIDNext))
{
articlesresponse.ResultList.Remove(articles);
}
else
{
i--;
}
}
So erscheint der Fehler:
System.ArgumentOutOfRangeException: Der Index lag ausserhalb des Bereichs. Er muss nicht negativ und kleiner als die Auflistung sein.
Hallo canuck,
ich sehe da kein Dictionary. 🙂
herbivore
Canuck, wenn du's sorum machen willst, darf das i-- nicht im else sztehen, sondern muss immer gemacht werden.
Und ausserdem den Iterator mit Count-1 initialisieren und auf ≥0 testen
Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca
Hallo canuck,
mein Vorschlag ist beschrieben in Grundlegendes zu Hashtables (Dictionaries) in dem Abschnitt, wo es um "Allerweltsworte" geht, wenn man continue durch Remove ersetzt.
Das eigentlich Löschen geht dann so:
Dictionary <String, Article> dictResult;
List <String> listDenied;
//...
foreach (String strArticleID in listDenied) {
dictResult.Remove (strArticleID);
}
herbivore
@MarsStein: Danke, so hat es geklappt
@herbivore: Ich werde mir das anschauen und den Check bei Gelegenheit noch anpassen, ebenfalls danke für deine Hilfe