it-swarm.com.de

Wie findet man die letzte Schleife in einem For Each (VB.NET)?

Wie kann ich feststellen, ob ich mich in der letzten Schleife einer For Each-Anweisung in VB.NET befinde?

23
EdenMachine

Die allgemeinen Sammlungen, für die Sie For Each ausführen können, implementieren die Schnittstelle IEnumerator . Diese Schnittstelle hat nur zwei Methoden, MoveNext und Reset, und eine Eigenschaft, Current.

Wenn Sie einen For Each für eine Sammlung verwenden, ruft dieser grundsätzlich die Funktion MoveNext auf und liest den zurückgegebenen Wert. Wenn der zurückgegebene Wert True ist, bedeutet dies, dass die Auflistung ein gültiges Element enthält und dass das Element über die Eigenschaft Current zurückgegeben wird. Wenn die Auflistung keine weiteren Elemente enthält, gibt die Funktion MoveNextFalse zurück und die Iteration wird beendet.

Aus der obigen Erklärung geht hervor, dass der For Each nicht die aktuelle Position in der Sammlung erfasst und daher die Antwort auf Ihre Frage ist ein kurzer Nein.

Wenn Sie jedoch immer noch wissen möchten, ob Sie sich im letzten Element Ihrer Sammlung befinden, können Sie den folgenden Code verwenden. Es prüft (unter Verwendung von LINQ), ob das aktuelle Element das letzte Element ist.

For Each item in Collection
    If item Is Collection.Last Then
        'do something with your last item'
    End If
Next
51
Alex Essilfie

Es wäre wahrscheinlich einfacher, nur eine For-Schleife anstelle von ForEach zu verwenden. Auf ähnliche Weise können Sie einen Zähler in Ihrer ForEach-Schleife belassen und prüfen, ob er yourCollection.Count - 1 entspricht. Dann befinden Sie sich in der letzten Iteration.

12
Strelok

Bei einem foreach können Sie dies erst dann feststellen, wenn es zu spät ist (dh wenn Sie nicht mehr auf dem Laufenden sind).

Hinweis: Ich gehe davon aus, dass Sie etwas verwenden, bei dem Sie nur eine IEnumerable-Schnittstelle haben. Wenn Sie eine Liste, ein Array usw. haben, befolgen Sie die anderen Antworten hier, wobei .Count oder Ähnliches verwendet wird, um herauszufinden, wie viele Elemente vorhanden sind. Auf diese Weise können Sie verfolgen, wo Sie sich in der Sammlung befinden.

Mit nur IEnumerable/IEnumerator gibt es jedoch keine Möglichkeit, sicher zu sein, ob es mehr gibt oder nicht, wenn Sie foreach verwenden.

Wenn Sie dies wissen müssen, verwenden Sie IEnumerable selbst. Dies ist, was foreach tut.

Die folgende Lösung ist für C #, sollte sich aber leicht in VB.NET übersetzen lassen:

List<Int32> nums = new List<Int32>();
nums.Add(1);
nums.Add(2);
nums.Add(3);

IEnumerator<Int32> enumerator = nums.GetEnumerator();
if (enumerator.MoveNext())
{
    // at least one value available
    while (true)
    {
        // make a copy of it
        Int32 current = enumerator.Current;

        // determine if it was the last value
        // if not, enumerator.Current is now the next value
        if (enumerator.MoveNext())
        {
            Console.Out.WriteLine("not last: " + current);
        }
        else
        {
            Console.Out.WriteLine("last: " + current);
            break;
        }
    }
}
enumerator.Dispose();

Dies wird drucken:

not last: 1
not last: 2
last: 3

Der Trick besteht darin, eine Kopie des aktuellen Werts zu erstellen und den Enumerator zu bitten, mit dem nächsten fortzufahren. Wenn dies fehlschlägt, war die von Ihnen erstellte Kopie tatsächlich der letzte Wert, ansonsten ist mehr vorhanden.

Kurze Antwort: Das kannst du nicht

Lange Antwort: Die Semantik einer For Each-Anweisung enthält keine Informationen darüber, ob Sie die erste, die letzte oder eine bestimmte Iteration ausführen.

For Each ist in die IEnumerable- und IEnumerable <> -Schnittstellen integriert, und das Verhalten hängt von der von Ihnen aufgerufenen Implementierung ab. Es ist zwar verwirrend, aber für die Auflistung gültig, dass Sie Elemente jedes Mal in einer anderen Reihenfolge zurückgeben. Zum Glück tut dies List <> nicht.

Wenn Sie wirklich wissen müssen, dass eine bestimmte Iteration die letzte ist, können Sie das letzte Element (im Voraus) identifizieren und dann eine andere Aktion ausführen, wenn Sie auf dieses Element stoßen.

Einfacher wäre es, die Iteration first zu erkennen (etwa durch einen Booleschen Wert) und dann etwas anderes zu tun.

Ein Beispiel (C #, aber das VB wird ähnlich sein):

StringBuilder result = new StringBuilder();
bool firstTime = true;
foreach(string s in names)
{
    if (!firstTime)
    {
        result.Append(", ");
    }

    result.Append(s);
    firstTime = false;
}
2
Bevan

Ich komme immer wieder auf diesen Beitrag zurück, also habe ich beschlossen, mich zu setzen und über dieses Problem nachzudenken.

    For Each obj In myCollection
        Console.WriteLine("current object: {0}", obj.ToString)

        If Object.ReferenceEquals(obj, myCollection.Last()) Then
            Console.WriteLine("current object is the last object")
        End If
    Next

Sie können die If...Then...End If -Anweisung sogar auf eine einzelne Zeile reduzieren, wenn Sie möchten. Ich bin mir nicht sicher, ob der Aufruf von .Last() bei jeder Iteration einen großen Einfluss auf die Leistung hat, aber Sie können ihn immer einer Variablen außerhalb der Schleife zuweisen, wenn Sie nachts dadurch wach bleiben.

1
Steven Liekens

Überprüfen Sie, ob das Element das letzte Element des Containers ist.

Warum willst du das machen?
Sie könnten einfach Anweisungen nach der Schleife platzieren. (Dass Sie auf dem letzten Element ausführen)

1
Tom Wijsman

Es wäre einfacher, eine For-Schleife anstelle einer ForEach-Schleife zu verwenden, Sie könnten jedoch so etwas tun

If item.Equals(itemCollection(itemCollection.Count)) Then
    ...
End If

innerhalb Ihrer ForEach-Schleife ... Angenommen, das Objekt hat die Equals-Methode ordnungsgemäß überschrieben.

Dies ist wahrscheinlich viel ressourcenintensiver als die Verwendung einer For-Schleife oder das Verfolgen des aktuellen Index in einer separaten Variablen.

Ich bin mir nicht sicher, ob dies die richtige Syntax ist. Es ist lange her, dass ich VB verwendet habe.

1
Rex Morgan

Verwenden einer Standardschleife "Für jede" ist dies nicht möglich. Mit einer "for Each" -Schleife können Sie sich auf die Daten anstelle der zugrunde liegenden Sammlung konzentrieren.

1
JaredPar

dieses Codebeispiel könnte helfen

For Each item in Collection
  If ReferenceEquals(Collection.Item(Collection.Count - 1), item) Then
    'do something with your last item'
  End If
Next
1
sh0hei

Angenommen, Sie arbeiten mit CheckBoxList

Dann könnte dieses Codebeispiel helfen:

Dim count As Integer = 0
Dim totalListCount As Integer = CheckBoxList.Items.Count()
For Each li In CheckBoxList.Items
         count += 1
           // This is the Last Item
      If count = totalListCount THEN
          // DO Somthing.....
      END IF
NEXT     
0
panky sharma

Wenn Sie an IEnumerable gebunden sind. Müssen Sie sich in der foreach-Schleife befinden? Wenn nicht, können Sie eine Variable direkt vor der foreach-Schleife deklarieren. Stellen Sie es während der Schleife ein. Dann benutze es nach der Schleife (wenn es nicht null ist)

0
Greg Dean

hier ist eine einfache Sache, die ich nicht weiß, ob sie politisch korrekt ist, aber funktioniert

for each item in listOfThings
   if(item = listOfThings.last)then 
       'you found the last loop
   end if
next 
0
bobby shneider