是否可以使用" zip()"使用步骤参数?

时间:2017-06-25 17:10:53

标签: python matrix multidimensional-array iterator

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

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

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

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

我正在使用Python中的2D数组处理面试练习题。

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

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

enter image description here

我知道我可以将网格子集化为前三行,如下所示:

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

我对打印进行了一些修改以使其显而易见,但此时,我想使用'步骤'来拉伸三个阵列。为了使每个新数组从每个数组中压缩3个值,然后再转到下一个数组。

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

  

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

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

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

3 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分: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'), ('.', '.', '.')]

答案 2 :(得分:1)

<强> 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', '.', '.', '.', '.', '.')
]

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