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

Повідомлення користувача про його поганий вхід так само важливо, як і пропуск його!
корисноБез

Відповіді:


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

Чи можете ви далі уточнити, що я б робив, якби я вклав петлі і хотів пропустити ітерацію одного з розширених? наприклад: for (int [] числа в numberarrays) {for (int number in numbers) {// Що робити, якщо потрібно стрибнути (numbers / numberarrays)}}
Брайан

C # 's gotoфактично корисний для ситуації, про яку питає @Brian. Додайте таку мітку, як nextArray:у нижній частині зовнішньої петлі, а потім, goto nextArray;коли потрібно перейти до неї.
Джейкоб Кралл

55

Інший підхід полягає у фільтруванні за допомогою LINQ до виконання циклу:

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

2
+1. Хоча це не є прямою відповіддю на питання, на практиці я б, мабуть, віддав перевагу цьому рішенню тому, яке я запропонував. Використання LINQ здається хорошим загальним випадком використання для фільтрації значень циклу, які ви не хочете обробляти.
Джон Фемінелла

3
Це просто охайніше, чи буде насправді швидше, якщо менше пропонувати? Я здогадуюсь, що LINQ значно оптимізований, але LINQ-розділ повинен буде прорисувати в якийсь момент так теоретично, якщо набір даних великий і отриманий "відфільтрований" підмножина майже такий же великий, то це буде повільніше, оскільки має відбуватися передбачення. двічі? То, може, це залежить від очікуваного результативного піднабору даних?
Чашки

25

Ви також можете перевернути свій тест:


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
Б Чарльз Н

8

Скористайтеся твердженням продовження:

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

3
Не розумію, чому це схвалено, це неправильно, оскільки він перебирає "o", а не "число"
Fortune

Погоджено, можливо це копія / вставка з попередніх відповідей? Концептуально цінні, оскільки це передбачення, але будь ласка, переконайтеся, що змінні є послідовними.
Антоніо Чіоліно

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.