我的情况是这样的
// 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;
}
}
-
也许您可以考虑使用
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 }
这是我能想到的最简单的方法之一。它准确地表示您想要的独立块。
-
如果你想更"紧凑"(代价是"很少"可读性),你可以考虑使用多变量单循环而不是单变量嵌套循环:
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 }
-
或者另一种不使用
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 识别)。
-
为了正确起见,修改后的解决方案将是这样的:
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 )
{
}