C# 是否有一种很好的方法来迭代范围中的每个整数,减去其中的 1

本文关键字:范围 整数 迭代 是否 方法 很好 一种 | 更新日期: 2023-09-27 18:31:15

我的情况是这样的

// radius is an int[]
for ( int i = 0; i < radius.length; ++i )
{
   for ( int j = 0; j < radius.length; ++j ) 
   {
       // do some stuff
   }  
}

除了我实际上想j通过范围0 - radius.length,但跳过i

{0,1,..., i-1, i+1, ..., radius.length}

我想知道是否有一种方法可以做到这一点,它是紧凑的、优雅的、高效的、可读的,甚至可能是正确的。

我打算怎么做

for ( int i = 0; i < radius.length; ++i )
{
   for ( int j = 0; j < radius.length; )
   {
       // do some stuff
       j += j != i ? 1 : 2;
   }
}

C# 是否有一种很好的方法来迭代范围中的每个整数,减去其中的 1

  1. 也许您可以考虑使用continue

    // radius is an int[]
    for (int i = 0; i < radius.length; ++i)    
       for (int j = 0; j < radius.length; ++j) 
       {
           if (i == j)
               continue;
           // do some stuff
       }  
    

    这是我能想到的最简单的方法之一。它准确地表示您想要的独立块。

  2. 如果你想更"紧凑"(代价是"很少"可读性),你可以考虑使用多变量单循环而不是单变量嵌套循环:

    int r = radius.Length;
    for (i = 0, j = 0; i < r - 1 || j < r; j++) {
        i += j == r ? 1 : 0;
        j %= r;
        if (i == j)
            continue;
        //do stuff
    }
    
  3. 或者另一种不使用continue的替代方案是(由米莉史密斯建议):

    for (int i = 0; i < radius.length; ++i)    
       for (int j = 0; j < radius.length; ++j)        
           if (i != j) {
               // do some stuff       
           }
    

    这样,至少您可以摆脱所有大括号,但在if.

注意:但我个人认为您的解决方案(使用j += j != i ? 1 : 2;已经非常紧凑,优雅,高效,可读!很难"击败"!;)

编辑:

"很难打败..."除了原始解决方案在i == 0 && j == 0时包含一个错误(由 Ivan Stoev 识别)。

  1. 为了正确起见,修改后的解决方案将是这样的:

    for ( int i = 0; i < radius.length; ++i )   
        for ( int j = 0; j < radius.length; )
        {
            // do some stuff
            j += j != i || i + j == 0 ? 1 : 2; //i + j == 0 condition added
        }    
    

这个怎么样?

var query = 
    from i in Enumerable.Range(0, radius.Length)
    from j in Enumerable.Range(0, radius.Length)
    where i != j
    select new { i, j };
foreach (var x in query)
{
    /* Do stuff with x.i && x.j */
}

我认为这是相当整洁的。

你可以把它构建到迭代器中:

        for (int i = 0; i < radius.length; i++)
        {
            for (int j = i == 0 ? 1 : 0; j < radius.length; j += j == i - 1 ? 2 : 1)
            {
                //-Do something
            }
        }

编辑:

将内部循环初始值设定项更新为:int j = i == 0 ? 1 : 0

另一种变体是使用循环和Range方法foreach

foreach(var i in Enumerable.Range(0,radius.length))
{
   foreach(var j in Enumerable.Range(0,radius.length).Where(r => r != i))
   {
     // do some stuff
   }
}

或者你甚至可以把它放在一个foreach循环中,但表达式不会很紧凑:

    var range = Enumerable.Range(0, radius.length)
               .SelectMany(i => Enumerable.Range(0, Enumerable.Range(0, radius.length)
                         .Where(r => r != i))
                         .Select(j => new {i, j}));
    foreach (var value in range)
    {
        value.i //i value
        value.j //j value
    }

上面演示的正统解决方案是continue语句,但如果 if 关键字在您的工作场所是禁忌,另一种方法是将循环一分为二:

for ( int j = 0; j < i; ++j ) 
{
}  
for ( int j = i+1; j < radius.Length; ++j ) 
{
}