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

时间:2016-01-20 06:13:31

标签: c# .net algorithm loops

我的情况就像是

// 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;
   }

}

5 个答案:

答案 0 :(得分:13)

  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的其他替代方案(由Millie Smith建议):

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

    这样,至少你可以摆脱if上的所有大括号。

  4. 注意:但我个人认为您的解决方案(使用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
          }    
      

答案 1 :(得分:6)

这个怎么样?

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 */
}

我认为这相当整洁。

答案 2 :(得分:2)

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

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
    }

答案 3 :(得分:2)

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

        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

答案 4 :(得分:0)

上面演示的正统解决方案是continue statement,但如果if关键字在您的工作场所是禁忌,则可以选择将循环拆分为两个:

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