¿Cómo omito una iteración de un bucle `foreach`?

324

En Perl puedo omitir una iteración foreach (o cualquier bucle) con un next;comando.

¿Hay alguna manera de saltear una iteración y saltar al siguiente ciclo en C #?

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

     // otherwise process number
 }
Brian
fuente
¡Notificar al usuario con su entrada incorrecta es tan importante como omitirlo!
útilBee

Respuestas:

664

Usted quiere:

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

    // do work
}

Aquí hay más sobre la continuepalabra clave .


Actualización: en respuesta a la pregunta de seguimiento de Brian en los comentarios:

¿Podría aclarar más qué haría si hubiera anidado los bucles y quisiera omitir la iteración de uno de los extendidos?

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

A continuesiempre se aplica al alcance envolvente más cercano, por lo que no podría usarlo para salir del bucle más externo. Si surge una condición como esa, necesitaría hacer algo más complicado dependiendo exactamente de lo que desea, como breakdel bucle interno y luego continuedel bucle externo. Consulte aquí la documentación sobre la breakpalabra clave . La breakpalabra clave C # es similar a la lastpalabra clave Perl .

Además, considere tomar la sugerencia de Dustin para simplemente filtrar los valores que no desea procesar de antemano:

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
fuente
¿Podría aclarar más qué haría si hubiera anidado los bucles y quisiera omitir la iteración de uno de los extendidos? ej .: for (int [] números en números numerados) {for (int número en números) {// Qué hacer si desea saltar los (números / números números)}}
Brian
C # gotoes realmente útil para la situación sobre la que @Brian está preguntando. Agregue una etiqueta, como nextArray:en la parte inferior del bucle externo, y luego goto nextArray;cuando desee omitirla.
Jacob Krall
55

Otro enfoque es filtrar usando LINQ antes de que se ejecute el bucle:

foreach ( int number in numbers.Where(n => n >= 0) )
{
    // process number
}
Dustin Campbell
fuente
2
+1. Aunque no es una respuesta directa a la pregunta, en la práctica probablemente preferiría esta solución a la que propuse. Usar LINQ parece un buen caso de uso general para filtrar valores de bucle que no desea procesar.
John Feminella
3
¿Es esto más ordenado o será más rápido porque hay menos para predicar? Supongo que LINQ está muy optimizado, pero la sección LINQ tendrá que predecir en algún momento, por lo que, en teoría, si el conjunto de datos es grande y el subconjunto 'filtrado' resultante es casi tan grande, entonces esto será más lento ya que un foreach tiene que suceder ¿dos veces? Entonces, ¿tal vez depende del subconjunto de datos resultante esperado?
Coops
25

También puede voltear su prueba if:


foreach ( int number in numbers )
{
     if ( number >= 0 )
     {
        //process number
     }
 }
crashmstr
fuente
:) ¡Gracias! Se me ocurrió un ejemplo básico porque había algunos criterios al comienzo del ciclo que no necesitarían ser procesados, y otros que eran errores que debían ser detectados.
Brian
44
La única respuesta basada en LINQ es agradable y tiene elegancia, pero usar una declaración if no está mal.
crashmstr
21
foreach ( int number in numbers )
{
    if ( number < 0 )
    {
        continue;
    }

    //otherwise process number
}
Tamas Czinege
fuente
16

Puedes usar la continuedeclaración.

Por ejemplo:

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

Otro enfoque que usa linq es:

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

Si desea omitir el primero de varios elementos.

O úselo .SkipWheresi desea especificar una condición para omitir.

Edmund Covington
fuente
Esta es la forma más simple (aunque tal vez la lógica interna es la misma) de hacer esto, ahora que tiene Linq disponible. Aunque debe asegurarse de que .Skip se llame solo una vez por razones de rendimiento. (Sí, ahora veo que esta no es la respuesta directa a la pregunta de OP, aunque es una valiosa adición a esta lista de respuestas). +1
B Charles H
8

Use la declaración de continuación:

foreach(object number in mycollection) {
     if( number < 0 ) {
         continue;
     }
  }
Drew
fuente
3
No entiendo por qué se votó, esto está mal ya que repite "o", no "número"
Fortune
De acuerdo, ¿tal vez se trata de copiar / pegar de respuestas anteriores? Conceptualmente valioso ya que es un foreach, pero asegúrese de que las variables sean consistentes.
Antonio Ciolino
0

La forma más fácil de hacerlo es la siguiente:

//Skip First Iteration

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

//Skip any other like 5th iteration

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