views:

3524

answers:

15

If I have a for loop which is nested within another, how can I efficiently come out of both loops (inner and outer) in the quickest possible way?

I don't want to have to use a boolean and then have to say go to another method, but rather just to execute the first line of code after the outer loop.

What is a quick and nice way of going about this?

Thanks

A: 

I think unless you want to do the "boolean thing" the only solution is actually to throw. Which you obviously shouldn't do..!

Thomas Hansen
+21  A: 

Well, "goto", but that is ugly... and not always possible. You can also place the loops into a method (or an anon-method) and use "return" to exit back to the main code.

        // goto
        for (int i = 0; i < 100; i++)
        {
            for (int j = 0; j < 100; j++)
            {
                goto Foo; // yeuck!
            }
        }
    Foo:
        Console.WriteLine("Hi");

        // anon-method
        Action work = delegate
        {
            for (int x = 0; x < 100; x++)
            {
                for (int y = 0; y < 100; y++)
                {
                    return; // exits anon-method
                }
            }
        };
        work(); // execute anon-method
        Console.WriteLine("Hi");
Marc Gravell
In this type of situation I don't think using goto is any worse than the normal use of something like break (after all they're both just unconditional branches to a label, it's just that with break the label is implicit).
Greg Beech
sometimes goto is less evil than the alternatives
seanb
GOTO is good and fine. This is why it exists in the C# (and mostly all) languages. I think it's just "cool to not like GOTO". BTW, this is the answer :)
Timothy Khouri
Er, how is goto less evil than the other alternative he mentions, a plain return statement? Don't we like functions now? It's been a few decades since we wrote everything in big huge chunk of code. Today, we have these things called "functions", which means you don't need to use goto. Try them.
jalf
Why use goto when you can use break?
BeowulfOF
@BeowulfOF - break will only break out of the inner loop, not the inner and outer loops.
Greg Beech
I think those two are the finest solutions. I think the use of goto can be justified here. And it's also suitable to a lot of other platforms (delphi in my case, which is why I looked this up)
Johannes Rudolph
Goto itself isn't ugly. What is ugly is abusing goto which results in spaghetti code. Using goto to break out of nested loop is perfectyly ok. Besides, note that all break, continue and return, from structural programming point of view, are hardly better than goto - basically they're the same thing, just in nicer packaging. That's why pure structural languages (such as original Pascal) lack all of three.
el.pescado
+6  A: 

Is it possible to refactor the nested for loop into a private method? That way you could simply 'return' out of the method to exit the loop.

NoizWaves
+2  A: 

Don't quote me on this, but you could use goto as suggested in the MSDN. There are other solutions, as including a flag that is checked in each iteration of both loops. Finally you could use an exception as a really heavyweight solution to your problem.

GOTO:

for ( int i = 0; i < 10; ++i ) {
   for ( int j = 0; j < 10; ++j ) {
      // code
      if ( break_condition ) goto End;
      // more code
   }
}
End:

Condition:

bool exit = false;
for ( int i = 0; i < 10 && !exit; ++i ) {
   for ( int j = 0; j < 10 && !exit; ++j ) {
      // code
      if ( break_condition ) {
         exit = true;
         break; // or continue
      }
      // more code
   }
}

Exception:

try {
    for ( int i = 0; i < 10 && !exit; ++i ) {
       for ( int j = 0; j < 10 && !exit; ++j ) {
          // code
          if ( break_condition ) {
             throw new Exception()
          }
          // more code
       }
    }
catch ( Exception e ) {}
David Rodríguez - dribeas
these are all hacky workarounds where it would be super clean to just factor into a method and use early return
Dustin Getz
:) right, that is a simple solution, but you will have to pass all required local data into the method as arguments... This is one of the few places where goto might be the appropriate solution
David Rodríguez - dribeas
The Condition method doesn't even work because "more code" will be executed one time after exiting the inner loop before exiting the outer loop. The GOTO method works but does exactly what the poster said they don't want to do. The Exception method works but is uglier and slower than GOTO.
Windows programmer
+9  A: 

Use a suitable guard in the outer loop. Set the guard in the inner loop before you break.

bool exitedInner = false;

for (int i = 0; i < N && !exitedInner; ++i) {

    .... some outer loop stuff

    for (int j = 0; j < M; ++j) {

        if (sometest) {
            exitedInner = true;
            break;
        }
    }
    if (!exitedInner) {
       ... more outer loop stuff
    }
}

Or better yet, abstract the inner loop into a method and exit the outer loop when it returns false.

for (int i = 0; i < N; ++i) {

    .... some outer loop stuff

    if (!doInner(i, N, M)) {
       break;
    }

    ... more outer loop stuff
}
tvanfosson
Except the OP said "I don't want to have to use a boolean".
LeopardSkinPillBoxHat
I read "boolean and goto" -- doesn't use a goto.
tvanfosson
Very Pascal-ish...I'd probably rather use a goto, though I ordinarily avoid them like the plague.
Jonathan Leffler
+5  A: 

factor into a function/method and use early return, or rearrange your loops into a while-clause. goto/exceptions/whatever are certainly not appropriate here.

def do_until_equal():
  foreach a:
    foreach b:
      if a==b: return
Dustin Getz
Simple, concise. I like it.
dviljoen
A: 

I was thinking that exceptions aren't cheap/should only be thrown in a truly exceptional condition etc. Hence I don't think this solution would be good from a performance perspective.

I don't feel it it is right to take advantage of the newer features in .NET (anon methods) to do something which is pretty fundamental.

Because of that, tvon (sorry can't spell full username!) has a nice solution.

Marc: Nice use of anon methods, and this too is great but because I could be in a job where we don't use a version of .NET/C# that supports anon methods, I need to know a traditional approach too.

dotnetdev
"tvon (sorry can't spell full username!)" -- Either look at the screen while typing, or use your mouse to copy and paste.
Windows programmer
Goto has been there since day 1. Anon methods was just an aside, but a regular method (as I mentioned) is a very valid option, available from day 1. If you find yourself stuck with 1.1 (no anon-methods), then you still have 2 our of the 3 options I mentioned ;-p
Marc Gravell
+1  A: 

You asked for a combination of quick, nice, no use of a boolean, no use of goto, and C#. You've ruled out all possible ways of doing what you want.

The most quick and least ugly way is to use a goto.

Windows programmer
+15  A: 

Don't know if it works in C#, but in C I often do this:

    for (int i = 0; i < 100; i++)
    {
        for (int j = 0; j < 100; j++)
        {
            if (exit_condition)
            {
                // cause the outer loop to break:
                i = INT_MAX;
                Console.WriteLine("Hi");
                // break the inner loop
                break;
            }
        }
    }
Nils Pipenbrinck
It works in c#, thanks.
DrG
A: 

Since I first saw break in C a couple of decades back, this problem has vexed me. I was hoping some language enhancement would have an extension to break which would work thus:

break; // our trusty friend, breaks out of current looping construct.
break 2; // breaks out of the current and it's parent looping construct.
break 3; // breaks out of 3 looping constructs.
break all; // totally decimates any looping constructs in force.
Jesse C. Slicer
Then a maintenance programmer will insert another level of nesting, will fix some of the break statements, and will break some of the other break statements. The fix for that is to break to a label instead. That has really been proposed, but pragmatists use goto a label instead.
Windows programmer
Wait, who does maintenance programming any more? :)
Jesse C. Slicer
On a side note, PHP offers the ability to do this.http://www.php.net/break
Chris Bartow
JavaScript even has labeled blocks/break statements.http://www.devguru.com/Technologies/ecmascript/quickref/break.html
David Grant
@Chris Bartow: cool! made my Christmas :)@David Grant: so it seems JS break == C's goto?
Jesse C. Slicer
D has labeled break/continues
BCS
A: 

Depending on your situation, you may be able to do this, but only if your not executing code AFTER the inner loop.

for (int i = 0; i < 100; i++)
{
    for (int j = 0; j < 100; j++)
    {
        i = 100;
        break;
    }
}

It's not elegent, but it may be the easiest solution depending on your problem.

Chris Bartow
A: 

I've seen a lot of examples that use "break" but none that use "continue".

It still would require a flag of some sort in the inner loop:

while( some_condition )
{
    // outer loop stuff
    ...

    bool get_out = false;
    for(...)
    {
        // inner loop stuff
        ...

        get_out = true;
        break;
    }

    if( get_out )
    {
        some_condition=false;
        continue;
    }

    // more out loop stuff
    ...

}
dviljoen
+1  A: 

For people who found this question via other languages, Javascript, Java, and D allows labeled breaks and continues:

outer: while(fn1())
{
   while(fn2())
   {
     if(fn3()) continue outer;
     if(fn4()) break outer;
   }
}
BCS
A: 

Hi guys,

Thanks for the suggestions. Saying a boolean is not acceptable is just being stubborn, and the suggestions with a boolean are fine.

Thanks again everyone

dotnetdev
A: 

how terminate nesed loop


int temp=1;
for(i=1;i<n&&temp;i++)
{
    for(j=1;j<m&&temp;j++)
    {
    if(n<0)
        flag=0;
    else
        printf("not");
    }
}
shibasish