Как пропустить итерацию цикла `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
     }
 }

:) Спасибо! Я привел простой пример, потому что в начале цикла были некоторые критерии, которые не нужно было обрабатывать, и другие, которые были ошибками, которые нужно было отловить.
Брайан

4
Ответ, основанный на одном LINQ, хорош и элегантен, но использование оператора if не является неправильным.
crashmstr


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

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))
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.