Как пропустить итерацию цикла `foreach`?

324

В Perl я могу пропустить итерацию foreach (или любой цикл) с помощью next;команды.

Есть ли способ пропустить итерацию и перейти к следующему циклу в C #?

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

     // otherwise process number
 }
Брайан
источник
Уведомление пользователя с его неверным вводом так же важно, как и его пропуск!
полезноBee

Ответы:

664

Вы хотите:

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

    // do work
}

Вот еще о continueключевом слове .


Обновление: в ответ на дополнительный вопрос Брайана в комментариях:

Не могли бы вы уточнить, что я буду делать, если бы я вложил в циклы и хотел пропустить итерацию одного из расширенных циклов?

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

A continueвсегда применяется к ближайшей охватывающей области, поэтому вы не можете использовать его, чтобы выйти из внешнего цикла. Если возникает такое условие, вам нужно сделать что-то более сложное в зависимости от того, что именно вы хотите, например, breakот внутреннего цикла, а затем continueот внешнего цикла. Смотрите здесь для документации по breakключевому слову . breakC # ключевое слово похож на Perl lastключевое слово.

Кроме того, рассмотрите предложение Дастина просто отфильтровать значения, которые вы не хотите обрабатывать заранее:

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.
  }
}
Джон Феминелла
источник
Не могли бы вы уточнить, что я буду делать, если бы я вложил в циклы и хотел пропустить итерацию одного из расширенных циклов? ex: for (int [] числа в numberarrays) {for (int число в числах) {// Что делать, если вы хотите перейти к (numbers / numberarrays)}}
Брайан
C # на gotoсамом деле полезен для ситуации, о которой спрашивает Брайан. Добавьте метку, например, nextArray:внизу внешнего цикла, а затем, goto nextArray;когда вы захотите перейти к ней.
Джейкоб Кралл
55

Другой подход заключается в фильтрации с использованием LINQ перед выполнением цикла:

foreach ( int number in numbers.Where(n => n >= 0) )
{
    // process number
}
Дастин Кэмпбелл
источник
2
+1. Хотя это не прямой ответ на вопрос, на практике я бы предпочел это решение тому, которое я предложил. Использование LINQ кажется хорошим примером общего применения для фильтрации значений цикла, которые вы не хотите обрабатывать.
Джон Феминелла
3
Это просто опрятно или на самом деле быстрее, потому что есть меньше, чтобы учиться? Я предполагаю, что LINQ значительно оптимизирован, но в некоторой точке секция LINQ должна будет использовать foreach так теоретически, если набор данных большой, а результирующее «отфильтрованное» подмножество почти такое же большое, тогда это будет медленнее, чем должен происходить foreach дважды? Так может это зависит от ожидаемого результирующего набора данных?
Coops
25

Вы также можете перевернуть свой тест if:


foreach ( int number in numbers )
{
     if ( number >= 0 )
     {
        //process number
     }
 }
crashmstr
источник
:) Спасибо! Я привел простой пример, потому что в начале цикла были некоторые критерии, которые не нужно было обрабатывать, и другие, которые были ошибками, которые нужно было отловить.
Брайан
4
Ответ, основанный на одном LINQ, хорош и элегантен, но использование оператора if не является неправильным.
crashmstr
21
foreach ( int number in numbers )
{
    if ( number < 0 )
    {
        continue;
    }

    //otherwise process number
}
Тамас Чинеге
источник
16

Вы можете использовать continueзаявление.

Например:

foreach(int number in numbers)
{
    if(number < 0)
    {
        continue;
    }
}
Кев
источник
16

Другой подход с использованием linq:

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

Если вы хотите пропустить первый в ряде пунктов.

Или используйте, .SkipWhereесли хотите указать условие пропуска.

Эдмунд Ковингтон
источник
Это самый простой (хотя, возможно, логика внутри та же самая) способ сделать это - теперь, когда у вас есть доступный Linq. Хотя вы должны убедиться, что .Skip вызывается только один раз по соображениям производительности. (Да, теперь я вижу, что это не прямой ответ на вопрос ОП, хотя и ценное дополнение к этому списку ответов). +1
B Чарльз H
8

Используйте оператор continue:

foreach(object number in mycollection) {
     if( number < 0 ) {
         continue;
     }
  }
drewh
источник
3
Не понимаю, почему за это проголосовали, это неправильно, потому что он зацикливается на «о», а не «число»
Fortune
Согласились, может это копия / вставка из предыдущих ответов? Концептуально ценно, поскольку это foreach, но, пожалуйста, убедитесь, что переменные согласованы.
Антонио Чолино
0

Самый простой способ сделать это, как показано ниже:

//Skip First Iteration

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

//Skip any other like 5th iteration

foreach ( int number in numbers.Skip(5))
Kashif
источник