Question

Please pardon me if this is a duplicate question. I have two nested for loops which will iteration for around mn times (the complexity is around 3k).

Inside these for loops, I have 3 If conditions based on what I do certain operations. I am trying to see if there are any ways to avoid these if conditions inside the for loop as these will be executed for mn times.

Below is the skeletal of existing implementation:

var conditionA = <set conditions for A>
var conditionB = <set conditions for B>
var conditionC = <set conditions for C>

foreach (var x in X)
{
  foreach (var y in Y)
  {
    if (conditionA)
    {
      //computeA ..makes use of x and y
    }
    if (conditionB)
    {
      //computeB..makes use of x and y
    }
    if (conditionC)
    {
      //computeC..makes use of x and y
    }
  } //end of inner foreach
} 

As you can see that all the 3 conditions are determined before foreach, is there any way I can get rid of redundant IF statements at each iteration?

Was it helpful?

Solution

One way to avoid those ifs inside the loops is to put them outside, by deciding which functions to call in advance:

//set the values of conditionA, conditionB and conditionC;

functionA = conditionA ? computeA : noOp
functionB = conditionB ? computeB : noOp
functionC = conditionC ? computeC : noOp

foreach (var x in X)
{
    foreach (var y in Y)
    {
        functionA(x,y)
        functionB(x,y)
        functionC(x,y)
    }
}

Of course, there's no guarantee this will be faster, but it "meets the brief".

Alternatively, if you wish to only call functions if needed, create a set of functions to call in advance and loop through them each time:

//set the values of conditionA, conditionB and conditionC;

Collection functions;
if (conditionA) functions += computeA
if (conditionB) functions += computeB
if (conditionC) functions += computeC

foreach (var x in X)
{
    foreach (var y in Y)
    {
        foreach (var f in functions)
        {
            f(x,y)
        }
    }
}

This approach runs the risk of being slower though as you are adding the creation of an iterator for the functions nm times to the process. Of course, you are avoiding making unnecessary function calls and avoiding unnecessary checks. So in some situations, it may even be faster.

OTHER TIPS

There are many ways. Here's a tidy one:

if (conditionA)
{
    foreach (var x in X)
    {
        foreach (var y in Y)
        {
            //computeA ..makes use of x and y
        }
    }
}

if (conditionB)
{
    foreach (var x in X)
    {
        foreach (var y in Y)
        {
            //computeB ..makes use of x and y
        }
    }
}

if (conditionC)
{
    foreach (var x in X)
    {
        foreach (var y in Y)
        {
            //computeC ..makes use of x and y
        }
    }
}

This assumes there are no dependencies, side effects, or otherwise reasons to care about order of execution of the computations or conditions.

If you're thinking that's inefficient I'll point out that your original is O(n2) while this one is O(3n2) which is the same complexity under Big O. Don't let thoughts of efficiency trap you in hard to read code.

I did promise tidy so here it is:

if (conditionA)
{
    A a = computeA(X, Y);
}
if (conditionB)
{
    B b = computeB(X, Y);
}
if (conditionC)
{
    C c = computeC(X, Y);
}

The cool thing about that is it makes the fact that you have an initialization problem really obvious.

You should use function instead of using multiple conditions. It will surely improve your efficiency as well as execution time.

You can just accept it as it is. The code is clear enough as it is. None of the proposed changes seems better to me in a meaningful way.

I’d ask myself what is the reason why you want to get rid of the ifs. As it is now, maintenance cost is very low, readability is good, performance is good.

Licensed under: CC-BY-SA with attribution
scroll top