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