打破嵌套循环[重复]

Posted

技术标签:

【中文标题】打破嵌套循环[重复]【英文标题】:Breaking out of nested loops [duplicate] 【发布时间】:2010-10-13 19:15:04 【问题描述】:

有没有比抛出异常更容易摆脱嵌套循环的方法? (在 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

【问题讨论】:

你也可以导入“sys”,当你想结束程序时写sys.exit() @LauroSkr 如果你想以后做点什么,那就不要了。 isBreak = False for x in range(1,4): if(isBreak): break for y in range(1,10): if(xy>16): isBreak = True break print(xy) if(x 【参考方案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

同样适用于更深的循环:

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

【讨论】:

对此的解释:psung.blogspot.com.au/2007/12/for-else-in-python.html 由于外部循环需要 continue 语句,因此在嵌套循环不是外部 for 循环中唯一代码的情况下,这通常无法正常工作。 OP 的例子可能太简单了。 您可以将continue 替换为ok = True,将break 替换为if not ok: break 一开始我以为else 的意思是在没有迭代的情况下执行该块。很高兴知道! 没有 cmets,这对于后来的任何人来说都很难理解。【参考方案2】:

至少有人建议过,还有rejected。我认为除了重复测试或重新组织代码之外,没有其他方法。有时候有点烦。

在rejection message 中,van Rossum 先生提到使用return,这真的很明智,我个人需要记住这一点。 :)

【讨论】:

我第二次使用return 语句。它迫使我在第二个函数中编写内部循环,但使代码更容易理解。 这种通用解决方案也适用于嵌套 for 循环后跟其他语句的情况。例如。在循环句子列表并使用多个 for 循环根据特定单词或数字的存在过滤掉特定句子时,然后在外部 for 循环结束时执行实际工作。 van Rossum 先生的解决方案在您使用发电机时不起作用,恕我直言,这是一个相当大的洞【参考方案3】:

如果您能够将循环代码提取到函数中,则可以随时使用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()
    ...

【讨论】:

在这种情况下只能使用嵌套函数... @bjd2385 好点,用嵌套函数更新帖子【参考方案4】:

使用 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 个 fors 的数组推导式,并随时中断。

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

【讨论】:

要做一个衬里:>>> print "\n".join(map(str,takewhile(lambda i: i 这并没有解决全面打破嵌套循环的主要问题 仅当您正在寻找一种方法来一次跳出一个循环,但仍然能够同时跳出两个循环。为此,您可以使用函数或异常。当您不需要一次跳出一个循环时,我发现这种方法更优雅。 这适用于简单的情况,但不适用于第二个范围依赖于第一个范围的任何情况。 当第二个范围依赖于第一个时,可以使用第二个解决方案。 IE y 位于for y in [...] 右侧的范围内。不知道那是多么pythonic,这几年我没有写太多python!【参考方案5】:

有时我使用布尔变量。天真,如果你愿意的话,但我觉得它读起来非常灵活和舒适。测试一个变量可以避免再次测试复杂的条件,也可以从内部循环中的多个测试中收集结果。

    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

【讨论】:

【参考方案6】:

如果您要引发异常,您可能会引发StopIteration exception。这至少会使意图显而易见。

【讨论】:

这是个好主意。它不需要创建一个新的异常类,而且非常容易阅读。 如果您的循环是更大的产量结构的一部分并且您没有很好地理解这一点,这可能会产生意想不到的副作用【参考方案7】:

您还可以重构代码以使用生成器。但这可能不是所有类型的嵌套循环的解决方案。

【讨论】:

【参考方案8】:

在这种特殊情况下,您可以使用 itertools.product 将循环与现代 python(3.0 和可能 2.6)合并。

我自己将此作为经验法则,如果您嵌套太多循环(例如,超过 2 个),您通常可以将其中一个循环提取到不同的方法中或将循环合并为一个,就像本例一样。

【讨论】:

以上是关于打破嵌套循环[重复]的主要内容,如果未能解决你的问题,请参考以下文章

打破 JavaScript 中嵌套循环的最佳方法是啥?

如何打破 Java 中的嵌套循环?

打破R中的嵌套循环

如何打破 Objective-C 中的两个嵌套 for 循环?

如何打破 Dart 中的嵌套循环

Python打破嵌套的for循环并重新启动while循环