我想使用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次两次。
我知道我可以将网格子集化为前三行,如下所示:
>>> 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)
非常感谢任何帮助。谢谢。
答案 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', '.', '.', '.', '.', '.')
]
我们最终得到了所有块的列表。现在你可以根据数独规则检查它们。