在 Python 中中断列表理解

我正在解决一个数独,我有一个约束列表。它们看起来像这样:


(1,2,[1,2,3])

每个元组都包含行号、列号和该位置的可能值。现在我有以下代码来进行此约束:


[(row, column, notIn(matrix[row - 1], getColumn(matrix, column),

           getSubgrid(matrix, row, column)))

           for row in range(1, len(matrix) + 1)

           for column in range(1, len(matrix) + 1)

           if matrix[row - 1][column - 1] == 0]

我正在努力使我的代码更有效率,我的程序现在一直在施加所有约束,但是当它找到只有一个可能值的约束时,我希望它停止,如下所示:


(3,4,[2])

我想在列表理解中找到这样的元素时打破它,但该元素必须包含在列表中。否则,我想在找到约束时返回约束。可能没有只有一个可能值的约束,在这种情况下,我仍然需要所有约束。


我该怎么做?


紫衣仙女
浏览 106回答 3
3回答

猛跑小猪

首先编写生成所有约束的生成器表达式(不是列表推导)。from itertools import productconstraints = ((r, c, notIn(matrix[r-1],                            getColumn(matrix, c),                            getSubgrid(matrix, r, c)))                for r, c in product(range(1, len(matrix) + 1), repeat=2)               if matrix[r-1][c-1] == 0)接下来,按条件筛选候选列表应只有一个元素。ready_to_fill = filter(lambda c: len(c[2]) == 1, constraints)现在,您可以完整地迭代ready_to_fillfor row, column, [value] in ready_to_fill:    matrix[row-1][column-1] = value或者只是得到第一个(请记住,你可能还没有找到一个准备好填充的正方形):try:    next_to_fill = next(ready_to_fill)except StopIteration:    ...在 Python 3.8 中,您可以使用赋值表达式来检查是否存在这样的约束,并使用以下命令获取对它的引用:any# No need for filter in this case# If any returns True, next_to_fill will be the first constraint# with a singleton list.if any(len((next_to_fill := c)[2]) == 1 for c in constraints):    ...更新:要使所有内容达到并包括单例列表约束,生成器表达式不太方便。不过,您可以使用生成器函数。def get_constraints():    for r, c in product(range(1, len(matrix) + 1), repeat=2):        if matrix[r-1][c-1]:            continue        v = notIn(matrix[r-1],                  getColumn(matrix, c),                  getSubgrid(matrix, r, c))        yield (r, c, v)        if len(v) == 1:            return for row, column, [value] in get_constraints():     ...

qq_花开花谢_0

假设您有一个函数,它只返回列表理解:def getConstraints(matrix):     return [(row, column, notIn(matrix[row - 1], getColumn(matrix, column),               getSubgrid(matrix, row, column)))               for row in range(1, len(matrix) + 1)               for column in range(1, len(matrix) + 1)               if matrix[row - 1][column - 1] == 0]我们可以很容易地将其重写为一个生成器,而不会破坏我们最初使用它的方式:yielddef getConstraints(matrix):    # probably can just use generator directly in most of your cases...    # but might as well keep this around for max compatibility.    return list(getConstraintsGENERATOR(matrix))def getConstraintsGENERATOR(matrix):    for row in range(1, len(matrix) + 1):        for column in range(1, len(matrix) + 1):            if matrix[row - 1][column - 1] == 0:                x = notIn(matrix[row - 1],                          getColumn(matrix, column),                          getSubgrid(matrix, row, column)                        )                yield (row, column, x)现在,因为我们有一个正在处理值的函数,所以在早期添加一个案例变得微不足道,在你的情况下,我认为它会是,并且由于你想包含该元素,你会在.yieldreturnif len(x) == 1: returnyield

蝴蝶不菲

只是请做一个正常的循环。我使用列表理解以清晰简洁的方式快速填充列表。这是相反的,我甚至不想理解它。这将使事情更难调试。这似乎与便利功能应该是什么相反。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python