web-dev-qa-db-ja.com

入れ子になったループから抜け出す

重複している可能性があります:
Pythonで複数のループから抜け出す方法は?

例外をスローするよりも、入れ子になったループから抜け出す簡単な方法はありますか? (Perlでは、各ループにラベルを付けて、少なくとも外側のループを続けることができます。)

for x in range(10):
    for y in range(10):
        print x*y
        if x*y > 50:
            "break both loops"

すなわち、より良い方法があります:

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
225
Michael Kuhn

少なくとも提案されていますが、 拒否された もあります。テストを繰り返したり、コードを再編成したりする以外に、他の方法はないと思います。それは時々少し面倒です。

拒否メッセージ の中で、van Rossum氏はreturnを使うことに言及しています。 :)

124
unwind
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

より深いループでも同じことが言えます。

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
619
Markus Jarderot

ループコードを関数に抽出できる場合は、いつでもreturnステートメントを使用して最も外側のループを終了できます。

def foo():
    for x in range(10):
        for y in range(10):
            print x*y
            if x*y > 50:
                return
foo()

その関数を抽出するのが難しい場合は、@ bjd2385が示唆するように内部関数を使用できます。

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()
    ...
57
Mr Fooz

Itertools.productを使用してください。

from itertools import product
for x, y in product(range(10), range(10)):
    #do whatever you want
    break

これがpythonドキュメントのitertools.productへのリンクです: http://docs.python.org/library/itertools.html#itertools.product

2つのforが含まれる配列内包表記をループ処理し、必要に応じて中断することもできます。

>>> [(x, y) for y in ['y1', 'y2'] for x in ['x1', 'x2']]
[
    ('x1', 'y1'), ('x2', 'y1'),
    ('x1', 'y2'), ('x2', 'y2')
]

(明確にするためにフォーマットされています)

38
Fábio Santos

時々私はブール変数を使用します。素朴です、あなたが望むなら、私はそれが読むのが非常に柔軟で快適であると思います。変数をテストすることは、再度複雑な条件をテストすることを避け、また内部ループのいくつかのテストから結果を集めることができます。

    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
21
Halberdier

あなたが例外を発生させるつもりなら、あなたは StopIteration例外 を発生させるかもしれません。それは少なくとも意図を明白にするでしょう。

16
dbn

ジェネレータを使用するようにコードをリファクタリングすることもできます。しかし、これはすべてのタイプのネストループの解決策とは限りません。

8
J S

この場合、itertools.productを使用して、ループを最新のpython(3.0およびおそらく2.6)にマージすることができます。

私は私自身の経験則としてこれを採用しました。あまりにも多くのループを入れ子にした場合(2つ以上)、このようにループの1つを別のメソッドに抽出するか、または1つにまとめることができます。場合。

3
Tetha