【问题标题】:Is it possible to use "zip()" with a step parameter?是否可以使用带有 step 参数的“zip()”?
【发布时间】:2017-11-28 15:24:41
【问题描述】:

我想使用 zip() 方法在 Python 中提取二维数组的一个非常特定的部分(并避免循环逻辑混乱)。我想使用 zip 来实现这样的目标:

>>> sub_matrix = list(zip([*grid[0:3]]*3))

# Desired output example (Option 1)
[".","4",".", ".",".","4",".",".","."]

# Desired output example (Option 2)
[[".","4","."],  
[".",".","4"],
[".",".","."]]

我正在 Python 中使用下面的二维数组来解决面试练习问题。

grid = [[".","4",".",".",".",".",".",".","."],
    [".",".","4",".",".",".",".",".","."],
    [".",".",".","1",".",".","7",".","."],
    [".",".",".",".",".",".",".",".","."],
    [".",".",".","3",".",".",".","6","."],
    [".",".",".",".",".","6",".","9","."],
    [".",".",".",".","1",".",".",".","."],
    [".",".",".",".",".",".","2",".","."],
    [".",".",".","8",".",".",".",".","."]]

解决该问题的一部分包括确保数独游戏中的每个 3 x 3“区域”都包含合法值。我想使用zip() 快速提取矩阵的 3 x 3 部分。例如,左上角的区域会导致测试失败,因为它包含 4 两次。

我知道我可以对网格进行子集化以获得前三行,如下所示:

    >>> sub_grid = grid[0:3]
    >>> print(sub_grid)
    [['.', '4', '.', '.', '.', '.', '.', '.', '.'], 
    ['.', '.', '4', '.', '.', '.', '.', '.', '.'], 
    ['.', '.', '.', '1', '.', '.', '7', '.', '.']]

我稍微修改了打印以使其更明显,但在这一点上,我想使用 3 的“步长”压缩三个数组,这样每个新数组都会从之前的每个数组中压缩 3 个值继续下一个。

Python3 docs on zip 中有一段我认为可以做到这一点的摘录,但我无法获得所需的输出。

保证迭代的从左到右的评估顺序。 这使得将数据系列聚类为 使用 zip(*[iter(s)]*n) 的 n 长度组。

(对于后代,问题来自 CodeFights will be hidden until unlocked

非常感谢任何帮助。谢谢。

【问题讨论】:

  • 在 numpy 中,这将是 grid[0:3, 0:3]

标签: python matrix multidimensional-array iterator


【解决方案1】:

没有拉链但是 [row[:3] for row in grid[:3]]

【讨论】:

  • 非常好的答案,谢谢。在勾选复选框之前,我会等着看是否有与 zip 相关的答案。干杯。
【解决方案2】:

zip 不支持以这种方式单步执行嵌套结构。另一个答案的另一种选择是使用map 并提取这些切片。

from operator import itemgetter
list(map(itemgetter(0, 1, 2), grid[0:3]))

或者,如果您愿意:

list(map(lambda x: x[0:3], grid[0:3]))

如果您使用的是 python2,则可以删除额外的 list(...)

至于使用什么技术以及为什么使用,请查看 SO 上的this 线程。

输出:

[('.', '4', '.'), ('.', '.', '4'), ('.', '.', '.')]

【讨论】:

    【解决方案3】:

    TL;DR

    要让块运行这个单行:

    [reduce(lambda a, b: a+b, item) for l in [zip(*row) for row in zip(*[iter([zip(*[iter(row)]*3) for row in grid])]*3)] for item in l]
    

    分步说明

    我们先来看看zip的使用方法:

    chunks = [zip(*[iter(row)]*3) for row in grid]
    
    [
        [('.', '4', '.'), ('.', '.', '.'), ('.', '.', '.')],
        [('.', '.', '4'), ('.', '.', '.'), ('.', '.', '.')],
        [('.', '.', '.'), ('1', '.', '.'), ('7', '.', '.')],
        [('.', '.', '.'), ('.', '.', '.'), ('.', '.', '.')],
        [('.', '.', '.'), ('3', '.', '.'), ('.', '6', '.')],
        [('.', '.', '.'), ('.', '.', '6'), ('.', '9', '.')],
        [('.', '.', '.'), ('.', '1', '.'), ('.', '.', '.')],
        [('.', '.', '.'), ('.', '.', '.'), ('2', '.', '.')],
        [('.', '.', '.'), ('8', '.', '.'), ('.', '.', '.')]
    ]
    

    您会看到每一行是如何分成大小为 3 的块的。行也应该被拆分,所以我们运行:

    blocks = zip(*[iter(chunks)]*3)
    
    [
        (
            [('.', '4', '.'), ('.', '.', '.'), ('.', '.', '.')],
            [('.', '.', '4'), ('.', '.', '.'), ('.', '.', '.')],
            [('.', '.', '.'), ('1', '.', '.'), ('7', '.', '.')]
        ), (
            [('.', '.', '.'), ('.', '.', '.'), ('.', '.', '.')],
            [('.', '.', '.'), ('3', '.', '.'), ('.', '6', '.')],
            [('.', '.', '.'), ('.', '.', '6'), ('.', '9', '.')]
        ), (
            [('.', '.', '.'), ('.', '1', '.'), ('.', '.', '.')],
            [('.', '.', '.'), ('.', '.', '.'), ('2', '.', '.')],
            [('.', '.', '.'), ('8', '.', '.'), ('.', '.', '.')]
        )
    ]
    

    这给了我们积木。对于提取,首先转置它们是有意义的:

    transposed_blocks = [zip(*row) for row in blocks]
    
    [
        [
            (('.', '4', '.'), ('.', '.', '4'), ('.', '.', '.')),
            (('.', '.', '.'), ('.', '.', '.'), ('1', '.', '.')),
            (('.', '.', '.'), ('.', '.', '.'), ('7', '.', '.'))
        ], [
            (('.', '.', '.'), ('.', '.', '.'), ('.', '.', '.')),
            (('.', '.', '.'), ('3', '.', '.'), ('.', '.', '6')),
            (('.', '.', '.'), ('.', '6', '.'), ('.', '9', '.'))
        ], [
            (('.', '.', '.'), ('.', '.', '.'), ('.', '.', '.')),
            (('.', '1', '.'), ('.', '.', '.'), ('8', '.', '.')),
            (('.', '.', '.'), ('2', '.', '.'), ('.', '.', '.'))
        ]
    ]
    

    您会看到每个块现在如何在自己的行上。最后一步是将每一行合并到一个列表中:

    blocks_as_list = [reduce(lambda a, b: a+b, item)
                      for l in transposed_blocks for item in l]
    
    [
        ('.', '4', '.', '.', '.', '4', '.', '.', '.'),
        ('.', '.', '.', '.', '.', '.', '1', '.', '.'),
        ('.', '.', '.', '.', '.', '.', '7', '.', '.'),
        ('.', '.', '.', '.', '.', '.', '.', '.', '.'),
        ('.', '.', '.', '3', '.', '.', '.', '.', '6'),
        ('.', '.', '.', '.', '6', '.', '.', '9', '.'),
        ('.', '.', '.', '.', '.', '.', '.', '.', '.'),
        ('.', '1', '.', '.', '.', '.', '8', '.', '.'),
        ('.', '.', '.', '2', '.', '.', '.', '.', '.')
    ]
    

    我们最终得到了所有块的列表。现在您可以对照数独规则检查它们。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-27
      • 1970-01-01
      • 2012-05-07
      • 2020-01-10
      相关资源
      最近更新 更多