cozzy
cozzy

Reputation: 147

Loops inside loops

I'd like to find easier way to write loops inside loops.
Here is example code of 3 levels of 'for' loops:

int level = 0;
int value = 0;
bool next = false;

for (int i0 = 0; i0 < 6; i0++)
{
    level = 0;
    value = i0;
    method();
    if (next)
    for (int i1 = 0; i1 < 6; i1++)
        {
            level = 1;
            value = i1;
            method();
            if (next)
            for (int i2 = 0; i2 < 6; i2++)
                {
                    level = 2;
                    value = i2;
                    method();
                    if (next)
                    {
                        //Do somethnig
                    }   
                }
        }
}



private void method()
    {
        //use int 'level' and 'value'
        //determine bool 'next'
    }

I wonder if it's possible to write the same thing different way. To set number of levels(number of loops) and loop repeats. In this case levels = 3; repeats = 6;. I need it because I am using more than 20 loops inside themselves and than the code is not comprehensible.

I hope my explanation was ok and thanks for help.

Upvotes: 0

Views: 394

Answers (6)

Note that the following isn't a complete solution to what you asked. Also, a recursion-based solution is probably more appropriate. However, I'm posting this answer as a possible alternate way of thinking about the problem.

What you could do to get rid of the loops is to calculate the "cross product" of the values of i0, i1, and i2 as follows:

foreach (var i in from i0 in Enumerable.Range(0, 6)
                  from i1 in Enumerable.Range(0, 6)
                  from i2 in Enumerable.Range(0, 6)
                  select Tuple.Create(i0, i1, i2))
{
    // i is now a tuple containing any combination of i0, i1, and i2.
}

(If you need more levels, simply add another from .. in .. and expand the tuple by passing another argument to Tuple.Create.)

The tuples will arrive in this order:

[0, 0, 0] 
[0, 0, 1]
  . . . 
[0, 0, 5] 
[0, 1, 0] 
[0, 1, 1]
  . . . 
[0, 1, 5] 
[1, 0, 0] 
[1, 0, 1]
  . . .

i.e. the same order as with your nested for loops.

This half-solution however requires that you change the way your method() currently works, since calls to that method can't be made "in-between" the tuple components' generation. One possibility might be to derive both level and value from the current tuple i and pass them into method as arguments. next could become the return value of method:

foreach (var i in ...)
{
    bool next = method(level: ..., value: ...);
    ...
}

Again, this is not intended as a final solution, but as a possibility to change around your code.

Upvotes: 1

Juliet
Juliet

Reputation: 81536

Go go gadget recursion!

public static void Loopy(int level, int maxLevel, int repeat)
{
    if (level > maxLevel)
        return;

    for (int i = 0; i < repeat; i++)
    {
        if (SomeMethod(level, i);)
            Loopy(level + 1, maxLevel, repeat);
    }
}

public static bool SomeMethod(int level, int i)
{
    Console.WriteLine("level: {0}, i: {1}", level, i);
    return ...
}

Upvotes: 5

Nir
Nir

Reputation: 25369

not very efficient but shorter is to use recursion which gets an array of counters as one parameter and the current level in the array as 2nd param.

then you can do something in the line of

paramsarray= array (4,5,6,3) ; //the depths of loops in each level
current_counts = array (0,0,0,0);

function loop (paramsarray, current_counts, depth){

if (depth> count(paramsarray) && ( index > paramsarray [depth])) return;// end recursion

// Do something here with current_counts as your current loop values

// 

current_counts[depth]++
if (current_counts[depth] > paramsarray[depth]) depth++
loop (paramsarray, current_counts, depth)
}

Upvotes: 0

BrokenGlass
BrokenGlass

Reputation: 161012

You could use recursion in this case:

public void doLevel(int level)
{
  for (int i = 0; i < 6; i++)
  { 
     if(method(i, level))
       doLevel(level +1);
  }
}

private bool method(int value, int level)
{
    //use int 'level' and 'value'
    //determine bool 'next'
}

Upvotes: 2

Saeed Amiri
Saeed Amiri

Reputation: 22565

Instead of loop use recursive call:

void recursiveCall(int currentLevel)
{
 if (currentLevel == 0)
   return;

 for (int i0 = 0; i0 < 6; i0++)
 {
    level = 0;
    value = i0;
    method();
    if (next)
      recursiveCall(currentLevel - 1);
 }
}

Upvotes: 2

Blindy
Blindy

Reputation: 67489

Are you looking for backtracking? 20 inner loops seems a bit excessive for anything else...

Upvotes: 1

Related Questions