昨天我正在进行游戏,我必须遍历一个二维数组并找到标记为“d”的任何单元格的位置(其中单元格表示为“ - ”表示空白或“d”表示为脏)
我使用两个for循环完成了这个:
def find_dirty_cells(board):
dirty_cells = []
for enum, row in enumerate(board):
for enumrow, cell in enumerate(row):
if cell == 'd':
dirty_cells.append((enum, enumrow))
return dirty_cells
但后来我认为构建一个生成器对象并返回它可能会更好,所以我写了这个:
def find_dirty_cells(board):
return ((enum, enumrow) for enumrow, cell in enumerate(row) for enum, row in enumerate(board) if cell == 'd')
但是第二个给出了不正确的数据响应(即,它没有找到'd'单元格)。必须有一些简单的东西,我忽略了第二个不等于第一个,但我看不到它。我试图解决的真正问题是:是否有一种简单的方法让我的第一次尝试返回生成器?
答案 0 :(得分:3)
您需要按照嵌套顺序列出for
循环:
def find_dirty_cells(board):
return ((enum, enumrow) for enum, row in enumerate(board) for enumrow, cell in enumerate(row) if cell == 'd')
您已经交换了enumerate(board)
和enumerate(row)
循环,这只有在您的会话或模块中仍有可用的全局row
变量时才有效。
在这种情况下,使用yield
代替dirty_cells.append()
只使用生成器函数而不是生成器表达式可能更容易:
def find_dirty_cells(board):
for enum, row in enumerate(board):
for enumrow, cell in enumerate(row):
if cell == 'd':
yield enum, enumrow
这将产生完全相同的效果,但可能更具可读性。
答案 1 :(得分:3)
要将原始函数干净地转换为生成器,您需要的是yield
语句,而不是return
(或在您的特定情况下,而不是append
)。我更喜欢这个版本的生成器表达式版本,因为原始版本远远超过readable。
def find_dirty_cells(board):
for enum, row in enumerate(board):
for enumrow, cell in enumerate(row):
if cell == 'd':
yield (enum, enumrow)
答案 2 :(得分:1)
这是使用numpy.ndenumerate()
执行此操作的简单方法:
from numpy import ndenumerate
find_dirty_cells = lambda a: (i for i,v in ndenumerate(a) if v=='d')
这也适用于具有2个以上维度的数组。