Wie überspringe ich eine Iteration einer foreach-Schleife?

324

In Perl kann ich eine foreach-Iteration (oder eine beliebige Schleifeniteration) mit einem next;Befehl überspringen .

Gibt es eine Möglichkeit, eine Iteration zu überspringen und zur nächsten Schleife in C # zu springen?

 foreach (int number in numbers)
 {
     if (number < 0)
     {
         // What goes here to skip over the loop?
     }

     // otherwise process number
 }
Brian
quelle
Es ist genauso wichtig, den Benutzer über seine fehlerhaften Eingaben zu informieren, wie sie zu überspringen!
nützlichBee

Antworten:

664

Sie wollen:

foreach (int number in numbers) //   <--- go back to here --------+
{                               //                                |
    if (number < 0)             //                                |
    {                           //                                |
        continue;   // Skip the remainder of this iteration. -----+
    }

    // do work
}

Hier erfahren Sie mehr über das continueSchlüsselwort .


Update: Als Antwort auf Brians Folgefrage in den Kommentaren:

Könnten Sie weiter klären, was ich tun würde, wenn ich für Schleifen verschachtelt wäre und die Iteration einer der erweiterten Schleifen überspringen wollte?

for (int[] numbers in numberarrays) {
  for (int number in numbers) { // What to do if I want to
                                // jump the (numbers/numberarrays)?
  }
}

A continuegilt immer für den nächstgelegenen umschließenden Bereich, sodass Sie ihn nicht verwenden können, um aus der äußersten Schleife auszubrechen. Wenn eine solche Bedingung auftritt, müssen Sie etwas Komplizierteres tun, je nachdem, was Sie genau möchten, z. B. breakvon der inneren Schleife und dann continuevon der äußeren Schleife. Hier finden Sie die Dokumentation zum breakSchlüsselwort . Das breakSchlüsselwort C # ähnelt dem lastSchlüsselwort Perl .

Nehmen Sie auch Dustins Vorschlag an, nur Werte herauszufiltern, die Sie nicht vorher verarbeiten möchten:

foreach (var basket in baskets.Where(b => b.IsOpen())) {
  foreach (var fruit in basket.Where(f => f.IsTasty())) {
    cuteAnimal.Eat(fruit); // Om nom nom. You don't need to break/continue
                           // since all the fruits that reach this point are
                           // in available baskets and tasty.
  }
}
John Feminella
quelle
Könnten Sie weiter klären, was ich tun würde, wenn ich für Schleifen verschachtelt wäre und die Iteration einer der erweiterten Schleifen überspringen wollte? Beispiel: für (int [] Zahlen in Zahlenfeldern) {für (int Zahlen in Zahlen) {// Was tun, wenn Sie die (Zahlen / Zahlenfelder) überspringen möchten}}
Brian
C # gotoist tatsächlich nützlich für die Situation, nach der @Brian fragt. Fügen Sie eine Beschriftung hinzu, z. B. nextArray:am unteren Rand der äußeren Schleife, und dann, goto nextArray;wenn Sie dorthin springen möchten.
Jacob Krall
55

Ein anderer Ansatz besteht darin, mit LINQ zu filtern, bevor die Schleife ausgeführt wird:

foreach ( int number in numbers.Where(n => n >= 0) )
{
    // process number
}
Dustin Campbell
quelle
2
+1. Obwohl dies keine direkte Antwort auf die Frage ist, würde ich diese Lösung in der Praxis wahrscheinlich der von mir vorgeschlagenen vorziehen. Die Verwendung von LINQ scheint ein guter allgemeiner Anwendungsfall zum Herausfiltern von Schleifenwerten zu sein, die Sie nicht verarbeiten möchten.
John Feminella
3
Ist das nur aufgeräumter oder geht es tatsächlich schneller, da weniger zu suchen ist? Ich vermute, dass LINQ stark optimiert ist, aber der LINQ-Abschnitt muss irgendwann foreach. Wenn also der Datensatz groß und die resultierende 'gefilterte' Teilmenge fast so groß ist, wird dies theoretisch langsamer sein, als ein foreach stattfinden muss zweimal? Vielleicht hängt es also vom erwarteten resultierenden Unterdatensatz ab?
Coops
25

Sie können Ihren if-Test auch umdrehen:


foreach ( int number in numbers )
{
     if ( number >= 0 )
     {
        //process number
     }
 }
Crashmstr
quelle
:) Vielen Dank! Ich habe mir ein einfaches Beispiel ausgedacht, weil es am Anfang der Schleife einige Kriterien gab, die nicht verarbeitet werden mussten, und andere, bei denen es sich um Fehler handelte, die abgefangen werden mussten.
Brian
4
Die eine LINQ-basierte Antwort ist nett und hat eine Eleganz, aber die Verwendung einer if-Anweisung ist nicht falsch.
Crashmstr
21
foreach ( int number in numbers )
{
    if ( number < 0 )
    {
        continue;
    }

    //otherwise process number
}
Tamas Czinege
quelle
16

Sie können die continueAnweisung verwenden.

Zum Beispiel:

foreach(int number in numbers)
{
    if(number < 0)
    {
        continue;
    }
}
Kev
quelle
16

Ein anderer Ansatz mit linq ist:

foreach ( int number in numbers.Skip(1))
{   
    // process number  
}

Wenn Sie den ersten in einer Reihe von Elementen überspringen möchten.

Oder verwenden .SkipWhereSie, wenn Sie eine Bedingung für das Überspringen angeben möchten.

Edmund Covington
quelle
Dies ist der einfachste Weg (obwohl die Logik im Inneren vielleicht dieselbe ist), dies zu tun - jetzt, da Sie Linq zur Verfügung haben. Sie sollten jedoch sicherstellen, dass .Skip aus Leistungsgründen nur einmal aufgerufen wird. (Ja, ich sehe jetzt, dass dies nicht die direkte Antwort auf die Frage von OP ist, obwohl dies eine wertvolle Ergänzung zu dieser Liste von Antworten ist). +1
B Charles H
8

Verwenden Sie die continue-Anweisung:

foreach(object number in mycollection) {
     if( number < 0 ) {
         continue;
     }
  }
zogh
quelle
3
Verstehe nicht, warum es positiv bewertet wird, das ist falsch, da er "o" und nicht "number" durchläuft
Fortune
Einverstanden, vielleicht ist dies ein Kopieren / Einfügen aus früheren Antworten? Konzeptionell wertvoll, da es ein Foreach ist, aber stellen Sie bitte sicher, dass die Variablen konsistent sind.
Antonio Ciolino
0

Der einfachste Weg, dies zu tun, ist wie folgt:

//Skip First Iteration

foreach ( int number in numbers.Skip(1))

//Skip any other like 5th iteration

foreach ( int number in numbers.Skip(5))
Kashif
quelle