The situation I have is like
// radius is an int[]
for ( int i = 0; i < radius.length; ++i )
{
for ( int j = 0; j < radius.length; ++j )
{
// do some stuff
}
}
Except I actually want j
to go through the range 0
-radius.length
, but skip over i
:
{0,1,..., i-1, i+1, ..., radius.length}
I'm wondering if there's a way to do this that is compact, elegant, efficient, readable, and maybe even correct.
How I planned to do it was
for ( int i = 0; i < radius.length; ++i )
{
for ( int j = 0; j < radius.length; )
{
// do some stuff
j += j != i ? 1 : 2;
}
}
Perhaps you may consider of using 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
}
That is one of the simplest I could think of. It is representing exactly what you want as an independent block.
If you want to be more "compact" (with the cost of "little" readability), you may consider of using multi-variables single loop instead of single variable nested loops:
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
}
Or another alternative without using continue
would be (suggested by Millie Smith):
for (int i = 0; i < radius.length; ++i)
for (int j = 0; j < radius.length; ++j)
if (i != j) {
// do some stuff
}
This way, at least you could get rid of all the curly brackets but on if
.
Note: But I personally think that your solution (using j += j != i ? 1 : 2;
) is already quite compact, elegant, efficient, readable! It is quite hard to "beat"! ;)
Edit:
"quite hard to beat..." except that the original solution contains a single error (as identified by Ivan Stoev) when i == 0 && j == 0
.
To make it right, a modified solution would be something like this:
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
}
How about this?
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 */
}
I think that's fairly neat.
You could build it into the iterator:
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
}
}
Edit:
Updated inner loop initializer to: int j = i == 0 ? 1 : 0
Another variant is using foreach
loop and Range
method:
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
}
}
Or you can even put it in one foreach
loop, but expression will be not very compact:
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
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With