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