Ich habe eine foreach
Schleife und muss eine Logik ausführen, wenn das letzte Element aus dem ausgewählt wird List
, z.
foreach (Item result in Model.Results)
{
//if current result is the last item in Model.Results
//then do something in the code
}
Kann ich wissen, welche Schleife die letzte ist, ohne for-Schleife und Zähler zu verwenden?
Antworten:
Wenn Sie nur etwas mit dem letzten Element tun müssen (im Gegensatz zu etwas anderem mit dem letzten Element, hilft die Verwendung von LINQ hier:
Wenn Sie mit dem letzten Element etwas anderes machen müssen, brauchen Sie etwas wie:
Obwohl Sie wahrscheinlich einen benutzerdefinierten Vergleich schreiben müssen, um sicherzustellen, dass Sie feststellen können, dass der Artikel mit dem von zurückgegebenen Artikel identisch ist
Last()
.Dieser Ansatz sollte mit Vorsicht angewendet werden, da er
Last
möglicherweise die Sammlung durchlaufen muss. Während dies für kleine Sammlungen möglicherweise kein Problem darstellt, kann es Auswirkungen auf die Leistung haben, wenn es groß wird. Es schlägt auch fehl, wenn die Liste doppelte Elemente enthält. In diesen Fällen kann so etwas angemessener sein:quelle
var last = Model.Result[Model.Result.Count - 1];
schneller als zu verwendenLast()
Wie wäre es mit einer guten, altmodischen Schleife?
Oder mit Linq und foreach:
quelle
Model.Results
es sich um eine handeltIEnumerable
. Sie könnenCount()
vor der Schleife aufrufen , dies kann jedoch zur vollständigen Iteration der Sequenz führen.Bei Verwendung
Last()
bestimmter Typen wird die gesamte Sammlung durchlaufen!Das heißt, wenn Sie einen
foreach
Anruf tätigen und einen Anruf tätigenLast()
, haben Sie zweimal eine Schleife durchgeführt ! Das möchten Sie sicher in großen Sammlungen vermeiden.Dann besteht die Lösung darin, eine
do while
Schleife zu verwenden:Wenn der Auflistungstyp nicht vom Typ ist , durchläuft
IList<T>
dieLast()
Funktion alle Auflistungselemente.Prüfung
Wenn Ihre Sammlung wahlfreien Zugriff bietet (z. B. Geräte)
IList<T>
), können Sie Ihren Artikel auch wie folgt überprüfen.quelle
using
Anweisung benötigt? Ich dachte, das wird nur benötigt, wenn ein Objekt Betriebssystemressourcen verwaltet, aber nicht für verwaltete Datenstrukturen.Wie Chris zeigt, wird Linq funktionieren; Verwenden Sie einfach Last (), um eine Referenz auf die letzte in der Aufzählung zu erhalten. Solange Sie nicht mit dieser Referenz arbeiten, führen Sie Ihren normalen Code aus. Wenn Sie jedoch mit dieser Referenz arbeiten, tun Sie Ihre zusätzliche Aufgabe. Sein Nachteil ist, dass es immer O (N) -Komplexität sein wird.
Sie können stattdessen Count () verwenden (dies ist O (1), wenn IEnumerable auch eine ICollection ist; dies gilt für die meisten gängigen integrierten IEnumerables) und Ihren foreach mit einem Zähler kombinieren:
quelle
quelle
foreach
. So :var lastItem = objList.LastOrDeafault();
. Von der Innenseite derforeach
Schleife aus können Sie dies folgendermaßen überprüfen :f (item.Equals(lastItem)) { ... }
. In Ihrer ursprünglichen AntwortobjList.LastOrDefault()
würde das bei jeder "foreach" -Iteration über die Sammlung iterieren ( Polinomialkomplexität ist beteiligt ).Wie Shimmy hervorgehoben hat, kann die Verwendung von Last () ein Leistungsproblem sein, beispielsweise wenn Ihre Sammlung das Live-Ergebnis eines LINQ-Ausdrucks ist. Um mehrere Iterationen zu verhindern, können Sie eine "ForEach" -Erweiterungsmethode wie die folgende verwenden:
Die Erweiterungsmethode sieht folgendermaßen aus (als zusätzlichen Bonus wird Ihnen auch der Index angezeigt und wenn Sie sich das erste Element ansehen):
quelle
Wenn Sie die Antwort von Daniel Wolf noch weiter verbessern , können Sie sie auf eine andere stapeln
IEnumerable
, um mehrere Iterationen und Lambdas zu vermeiden, wie z.Die Implementierung der Erweiterungsmethode:
quelle
foreach
, was eine Verbesserung ist.Die Iterator-Implementierung bietet dies nicht. Ihre Sammlung ist möglicherweise
IList
über einen Index in O (1) zugänglich. In diesem Fall können Sie eine normalefor
Schleife verwenden:Wenn Sie die Anzahl kennen, aber nicht über Indizes zugreifen können (Ergebnis ist also ein
ICollection
), können Sie sich selbst zählen, indem Sie eini
imforeach
Körper des Inkrements erhöhen und es mit der Länge vergleichen.Das alles ist nicht perfekt elegant. Chris 'Lösung ist vielleicht die schönste, die ich bisher gesehen habe.
quelle
Was ist mit einem etwas einfacheren Ansatz?
quelle
Der beste Ansatz wäre wahrscheinlich, nur diesen Schritt nach der Schleife auszuführen: z
Oder wenn Sie etwas für das letzte Ergebnis tun müssen
quelle
Die akzeptierte Antwort funktioniert nicht für Duplikate in der Sammlung. Wenn Sie auf eingestellt sind
foreach
, können Sie einfach Ihre eigenen Indexvariablen hinzufügen.quelle
mit Linq und dem foreach:
https://code.i-harness.com/de/q/7213ce
quelle
".Last ()" hat bei mir nicht funktioniert, also musste ich so etwas machen:
quelle
Wenn Sie einige kleine Anpassungen am hervorragenden Code von Jon Skeet vornehmen, können Sie ihn sogar intelligenter gestalten, indem Sie den Zugriff auf das vorherige und das nächste Element zulassen. Dies bedeutet natürlich, dass Sie 1 Punkt in der Implementierung vorlesen müssen. Aus Leistungsgründen werden das vorherige und das nächste Element nur für das aktuelle Iterationselement beibehalten. Es geht so:
quelle
So konvertieren Sie
foreach
, um auf das letzte Element zu reagieren:quelle
Speichern Sie einfach den vorherigen Wert und arbeiten Sie damit in der Schleife. Am Ende ist der 'vorherige' Wert das letzte Element, sodass Sie anders damit umgehen können. Keine Zählung oder spezielle Bibliotheken erforderlich.
quelle
Sie können einfach eine for-Schleife verwenden und es ist nicht erforderlich, eine zusätzliche
if
imfor
Körper hinzuzufügen :Der
-1
imfor
Zustand befindliche sorgt dafür, dass der letzte Gegenstand übersprungen wird.quelle
Jon Skeet hat vor einiger Zeit einen
SmartEnumerable<T>
Typ erstellt , um genau dieses Problem zu lösen. Sie können die Implementierung hier sehen:http://codeblog.jonskeet.uk/2007/07/27/smart-enumerations/
Zum Herunterladen: http://www.yoda.arachsys.com/csharp/miscutil/
quelle
Um für jedes Element außer dem letzten etwas zusätzliches zu tun, kann ein funktionsbasierter Ansatz verwendet werden.
Dieser Ansatz hat offensichtliche Nachteile: weniger Codeklarheit für komplexere Fälle. Das Anrufen von Delegierten ist möglicherweise nicht sehr effektiv. Die Fehlerbehebung ist möglicherweise nicht ganz einfach. Die gute Seite - Codierung macht Spaß!
Trotzdem würde ich vorschlagen, in trivialen Fällen Plain for Loops zu verwenden, wenn Sie wissen, dass die Anzahl Ihrer Sammlungen nicht besonders langsam ist.
quelle
Eine andere Möglichkeit, die ich nicht gesehen habe, ist die Verwendung einer Warteschlange. Es ist analog zu einer Möglichkeit, eine SkipLast () -Methode zu implementieren, ohne mehr als nötig zu iterieren. Auf diese Weise können Sie dies auch für eine beliebige Anzahl von letzten Elementen tun.
Um dies zu nennen, gehen Sie wie folgt vor:
quelle
quelle
Sie können eine speziell dafür vorgesehene Erweiterungsmethode erstellen:
und Sie können es so verwenden:
quelle
Basierend auf der Antwort von @ Shimmy habe ich eine Erweiterungsmethode erstellt, die die Lösung ist, die jeder möchte. Es ist einfach, benutzerfreundlich und durchläuft die Sammlung nur einmal.
Dies funktioniert auf jedem
IEnumerable<T>
. Die Verwendung sieht folgendermaßen aus:Die Ausgabe sieht aus wie:
Darüber hinaus können Sie dies zu einer
Select
Stilmethode machen. Verwenden Sie diese Erweiterung dann in derForEach
. Dieser Code sieht folgendermaßen aus:quelle
Wir können den letzten Artikel in der Schleife überprüfen.
quelle
quelle
Sie können dies tun:
quelle