为了账号安全,请及时绑定邮箱和手机立即绑定

在 Python 中中断列表理解

在 Python 中中断列表理解

紫衣仙女 2022-08-16 18:43:39
我正在解决一个数独,我有一个约束列表。它们看起来像这样:(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])我想在列表理解中找到这样的元素时打破它,但该元素必须包含在列表中。否则,我想在找到约束时返回约束。可能没有只有一个可能值的约束,在这种情况下,我仍然需要所有约束。我该怎么做?
查看完整描述

3 回答

?
猛跑小猪

TA贡献1858条经验 获得超8个赞

首先编写生成所有约束的生成器表达式(不是列表推导)。


from itertools import product



constraints = ((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_fill


for 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():

     ...


查看完整回答
反对 回复 2022-08-16
?
qq_花开花谢_0

TA贡献1835条经验 获得超7个赞

假设您有一个函数,它只返回列表理解:


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]

我们可以很容易地将其重写为一个生成器,而不会破坏我们最初使用它的方式:yield


def 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


查看完整回答
反对 回复 2022-08-16
?
蝴蝶不菲

TA贡献1810条经验 获得超4个赞

只是请做一个正常的循环。我使用列表理解以清晰简洁的方式快速填充列表。这是相反的,我甚至不想理解它。

这将使事情更难调试。这似乎与便利功能应该是什么相反。


查看完整回答
反对 回复 2022-08-16
  • 3 回答
  • 0 关注
  • 100 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信