返回生成器而不是二维数组中的位置列表

时间:2013-07-01 15:18:26

标签: python python-3.x generator

昨天我正在进行游戏,我必须遍历一个二维数组并找到标记为“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'单元格)。必须有一些简单的东西,我忽略了第二个不等于第一个,但我看不到它。我试图解决的真正问题是:是否有一种简单的方法让我的第一次尝试返回生成器?

3 个答案:

答案 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个以上维度的数组。