Breaking out of nested loops [duplicate]
Is there an easier way to break out of nested loops than throwing an exception? (In Perl, you can give labels to each loop and at least continue an outer loop.)
for x in range(10):
for y in range(10):
print x*y
if x*y > 50:
"break both loops"
I.e., is there a nicer way than:
class BreakIt(Exception): pass
try:
for x in range(10):
for y in range(10):
print x*y
if x*y > 50:
raise BreakIt
except BreakIt:
pass
Solution 1:
for x in xrange(10):
for y in xrange(10):
print x*y
if x*y > 50:
break
else:
continue # only executed if the inner loop did NOT break
break # only executed if the inner loop DID break
The same works for deeper loops:
for x in xrange(10):
for y in xrange(10):
for z in xrange(10):
print x,y,z
if x*y*z == 30:
break
else:
continue
break
else:
continue
break
Solution 2:
It has at least been suggested, but also rejected. I don't think there is another way, short of repeating the test or re-organizing the code. It is sometimes a bit annoying.
In the rejection message, Mr van Rossum mentions using return
, which is really sensible and something I need to remember personally. :)
Solution 3:
If you're able to extract the loop code into a function, a return
statement can be used to exit the outermost loop at any time.
def foo():
for x in range(10):
for y in range(10):
print(x*y)
if x*y > 50:
return
foo()
If it's hard to extract that function you could use an inner function, as @bjd2385 suggests, e.g.
def your_outer_func():
...
def inner_func():
for x in range(10):
for y in range(10):
print(x*y)
if x*y > 50:
return
inner_func()
...
Solution 4:
Use itertools.product!
from itertools import product
for x, y in product(range(10), range(10)):
#do whatever you want
break
Here's a link to itertools.product in the python documentation: http://docs.python.org/library/itertools.html#itertools.product
You can also loop over an array comprehension with 2 fors in it, and break whenever you want to.
>>> [(x, y) for y in ['y1', 'y2'] for x in ['x1', 'x2']]
[
('x1', 'y1'), ('x2', 'y1'),
('x1', 'y2'), ('x2', 'y2')
]
Solution 5:
Sometimes I use a boolean variable. Naive, if you want, but I find it quite flexible and comfortable to read. Testing a variable may avoid testing again complex conditions and may also collect results from several tests in inner loops.
x_loop_must_break = False
for x in range(10):
for y in range(10):
print x*y
if x*y > 50:
x_loop_must_break = True
break
if x_loop_must_break: break