Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iterating from 1..n or n..1 conditionally in C++

I have a code that looks something like this:

bool var = some condition...
if( var )
{
     for( int i=0; i<10; ++i )
     {
         //execute some code ...
     }
}
else
{
     for( int i=9; i>=0; --i )
     {
         //execute some other code...
     }
}

However, the code that needs to be executed inside the for loop is almost entirely identical, and so I don't want to write it twice. I know I can do something like this:

bool var = some condition...
for( int i = (var ? 0 : 9 ); (var ? i<10 : i>=0 ); (var ? ++i : --i ) )
{
    //Execute my code
}

But this is a really un-elegant solution.

Is there a short, more elegant way of doing this? I checked std::iterator but I don't think it's what I need.

like image 492
Niv Avatar asked Dec 20 '22 15:12

Niv


2 Answers

You're focusing on the wrong problem here. If you have a direction flag, don't get all hung up on the iteration variable being literally correct. Just interpret it as required:

for (int i = 0; i < n; ++i)
{
   int j = var ? i : n - 1 - i;

   // j goes from 0..n-1 or n-1..0
}

Unless you're doing billions of these calls, the overhead of the secondary variable will be insignificant.

like image 80
tadman Avatar answered Jan 06 '23 13:01

tadman


You can just break the body of the loop out into a function/method and pass in sufficient context for the operation to occur. If the loop body uses mostly fields on this, making it a method should be fairly easy. Otherwise, you shouldn't need more parameters than the loop currently has.

If you're using C++11, you could implement this as a lambda capturing any necessary info, and call the lambda from within each of the loops (so as not to have a loose function). Using a function or method you can test independently is a good idea, though.

Does the code inside the loop depend on the value of the iterator, and if so, how? You might be able to use some basic math in a clever fashion, like transforming the start/end to always be 1..n, or using abs and negatives. This would leave you with one loop, and moving the body out into a function wouldn't be strictly necessary.

like image 27
ssube Avatar answered Jan 06 '23 13:01

ssube