如何跳过一个 `foreach` 循环的迭代?

381

在Perl中,我可以通过使用next;命令跳过foreach(或任何循环)迭代。

在C#中,有没有一种方法可以跳过一个迭代并跳到下一个循环?

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

     // otherwise process number
 }

通知用户他们的错误输入与跳过它一样重要! - usefulBee
8个回答

795

您需要:

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

    // do work
}

这里更多关于continue关键字的信息,请参阅continue关键字


更新:针对布莱恩在评论中的后续问题,以下是解答:

Could you further clarify what I would do if I had nested for loops, and wanted to skip the iteration of one of the extended ones?

for (int[] numbers in numberarrays) {
  for (int number in numbers) { // What to do if I want to
                                // jump the (numbers/numberarrays)?
  }
}
continue语句总是应用于最近的封闭作用域,因此您无法使用它来跳出最外层循环。如果出现这样的情况,您需要根据确切需求执行更复杂的操作,例如从内部循环中break,然后在外部循环中执行continue。有关break关键字的文档,请参见此处。C#的break关键字类似于Perl的last关键字。
另外,请考虑采用Dustin的建议,在处理之前仅过滤掉不需要处理的值:
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.
  }
}

1
如果我有嵌套的for循环,并且想跳过其中一个循环的迭代,你能否进一步澄清我该怎么做?例如:for (int[] numbers in numberarrays) { for (int number in numbers) { //如果要跳过(numbers/numberarrays)中的某个循环,该怎么办? } } - Brian
1
C#的goto在Brian所询问的情况下实际上非常有用。在外部循环的底部添加一个标签,例如nextArray:,然后当您想要跳转到它时,使用goto nextArray; - Jacob Krall

60

另一种方法是在循环执行之前使用 LINQ 进行过滤:

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

3
尽管这不是对问题的直接回答,但在实践中,我可能更喜欢这个解决方案而不是我提出的那个。使用LINQ似乎是过滤掉不想要处理的循环值的好方法。 - John Feminella
3
这只是更整洁还是实际上更快,因为foreach的内容更少?我猜LINQ已经被大大优化了,但LINQ部分最终仍需要执行foreach,因此理论上,如果数据集很大且结果“过滤”子集几乎同样大,则这将会更慢,因为foreach必须发生两次?因此可能取决于预期的子数据集结果。 - Paul C

28
你也可以翻转你的 if 测试:

foreach ( int number in numbers )
{
     if ( number >= 0 )
     {
        //process number
     }
 }

我提供了一个基本示例,因为循环开始时有一些不需要处理的条件,还有一些需要捕获的错误。 - Brian
4
使用基于LINQ的答案很好,并且具有优雅性,但使用 if 语句也并不是错误的。 - crashmstr

25
foreach ( int number in numbers )
{
    if ( number < 0 )
    {
        continue;
    }

    //otherwise process number
}

18
你可以使用 continue 语句。 例如:
foreach(int number in numbers)
{
    if(number < 0)
    {
        continue;
    }
}

16

使用 LINQ 的另一种方法是:

foreach ( int number in numbers.Skip(1))
{   
    // process number  
}
如果你想跳过一系列项目中的第一个,请使用`.Skip(1)`。
如果你想指定一个条件来跳过项目,请使用`.SkipWhere`。

1
这是最简单的(虽然内部逻辑可能相同)方法 - 现在您可以使用Linq。 但出于性能原因,您应确保仅调用一次.Skip。(是的,我现在看到这不是对OP问题的直接回答,但它是答案列表中有价值的补充)。+1 - B Charles H
1
这与问题无关。它将跳过前n个元素,而不是小于0的元素。 - Artur Michajluk
将此答案投票下降的原因是:没有解决原始问题,并且因为它首先有无用(错误)的skip()示例,其次才是可用(但质量低)的示例。了解SkipWhere()很好-但我同意B Charles H的评论:如果有大量迭代,每次都检查会很糟糕。 - qxotk

13

使用 continue 语句:

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

3
不理解为什么这篇文章会被点赞,因为他遍历的是“o”而不是“number”,这是错误的。 - Fortune
同意,也许这是从以前的答案复制/粘贴来的?从概念上讲很有价值,因为它是一个foreach,但请确保变量是一致的。 - Antonio Ciolino

-3

最简单的方法就是像下面这样:

//Skip First Iteration

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

//Skip any other like 5th iteration

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

这与问题有什么关系呢?你所做的只是跳过第一个(或前五个)元素,而不考虑任何其他条件。原帖作者想知道如何跳过一个迭代(任何一个)并继续下一个。 - Peter Abolins

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接