Comment ignorer une itération d'une boucle `foreach`?


324

En Perl, je peux ignorer une itération foreach (ou n'importe quelle boucle) avec une next;commande.

Existe-t-il un moyen de sauter une itération et de passer à la boucle suivante en C #?

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

     // otherwise process number
 }

Avertir l'utilisateur de sa mauvaise entrée est aussi important que de le sauter!
utileBee

Réponses:


664

Tu veux:

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

    // do work
}

Voici plus sur le continuemot - clé .


Mise à jour: En réponse à la question de suivi de Brian dans les commentaires:

Pourriez-vous clarifier davantage ce que je ferais si j'avais imbriqué des boucles et que je voulais ignorer l'itération de l'une des extensions?

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

Un continues'applique toujours à la portée englobante la plus proche, vous ne pouvez donc pas l'utiliser pour sortir de la boucle la plus externe. Si une telle condition survient, vous devrez faire quelque chose de plus compliqué en fonction de ce que vous voulez exactement, comme breakde la boucle intérieure, puis continuede la boucle extérieure. Voir ici pour la documentation sur le breakmot - clé . Le breakmot clé C # est similaire au lastmot clé Perl .

En outre, pensez à prendre la suggestion de Dustin pour filtrer simplement les valeurs que vous ne souhaitez pas traiter à l'avance:

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.
  }
}

Pourriez-vous clarifier davantage ce que je ferais si j'avais imbriqué des boucles et que je voulais ignorer l'itération de l'une des extensions? ex: for (int [] nombres dans les tableaux de nombres) {for (int nombre dans les nombres) {// Que faire si vous voulez sauter les (nombres / tableaux de nombres)}}
Brian

Les C # gotosont en fait utiles pour la situation à propos de laquelle @Brian demande. Ajoutez une étiquette comme nextArray:au bas de la boucle externe, puis goto nextArray;lorsque vous souhaitez y accéder.
Jacob Krall

55

Une autre approche consiste à filtrer à l'aide de LINQ avant l'exécution de la boucle:

foreach ( int number in numbers.Where(n => n >= 0) )
{
    // process number
}

2
+1. Bien que ce ne soit pas une réponse directe à la question, dans la pratique, je préférerais probablement cette solution à celle que j'ai proposée. L'utilisation de LINQ semble être un bon cas d'utilisation général pour filtrer les valeurs de boucle que vous ne souhaitez pas traiter.
John Feminella

3
Est-ce juste plus ordonné ou sera-t-il plus rapide dans la mesure où il y a moins à faire? Je suppose que LINQ est grandement optimisé, mais la section LINQ devra foreach à un moment donné, donc théoriquement si l'ensemble de données est grand et que le sous-ensemble `` filtré '' résultant est presque aussi grand, alors ce sera plus lent qu'une foreach doit se produire deux fois? Alors, cela dépend peut-être du sous-ensemble de données résultant attendu?
Coops

25

Vous pouvez également retourner votre test if:


foreach ( int number in numbers )
{
     if ( number >= 0 )
     {
        //process number
     }
 }

:) Merci! Je viens avec un exemple de base parce qu'il y avait certains critères au début de la boucle qui n'auraient pas besoin d'être traités, et d'autres qui étaient des erreurs qui devaient être détectées.
Brian

4
La seule réponse basée sur LINQ est agréable et a une élégance, mais utiliser une instruction if n'est pas faux.
crashmstr

21
foreach ( int number in numbers )
{
    if ( number < 0 )
    {
        continue;
    }

    //otherwise process number
}

16

Vous pouvez utiliser l' continueinstruction.

Par exemple:

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

16

Une autre approche utilisant linq est:

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

Si vous souhaitez ignorer le premier élément d'un certain nombre d'éléments.

Ou utilisez .SkipWheresi vous souhaitez spécifier une condition de saut.


C'est la façon la plus simple (bien que la logique à l'intérieur soit la même) de le faire - maintenant que Linq est disponible. Vous devez toutefois vous assurer que .Skip n'est appelé qu'une seule fois pour des raisons de performances. (Oui, je vois maintenant que ce n'est pas la réponse directe à la question d'OP, bien qu'un ajout précieux à cette liste de réponses). +1
B Charles H

8

Utilisez l'instruction continue:

foreach(object number in mycollection) {
     if( number < 0 ) {
         continue;
     }
  }

3
Je ne comprends pas pourquoi il est voté positivement, c'est faux car il boucle sur "o", pas sur "number"
Fortune

D'accord, c'est peut-être un copier / coller des réponses précédentes? Conceptuellement utile car c'est un foreach, mais assurez-vous que les variables sont cohérentes.
Antonio Ciolino

0

La façon la plus simple de le faire est comme ci-dessous:

//Skip First Iteration

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

//Skip any other like 5th iteration

foreach ( int number in numbers.Skip(5))
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.