【问题标题】:Return generator instead of list of locations from a 2d Array返回生成器而不是二维数组中的位置列表
【发布时间】:2013-07-01 15:18:26
【问题描述】:

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

【问题讨论】:

    标签: python python-3.x generator


    【解决方案1】:

    您需要按照嵌套顺序列出您的 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
    

    这将具有完全相同的效果,但可能更具可读性。

    【讨论】:

    • 感谢您的精彩解释。我知道一些简单的事情让我绊倒了,我想我仍然对理解感到困惑。我同意产量版本更具可读性。谢谢。
    【解决方案2】:

    要将您的原始函数干净地转换为生成器,您需要的是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)
    

    【讨论】:

      【解决方案3】:

      使用numpy.ndenumerate() 是一种直接的方法:

      from numpy import ndenumerate
      find_dirty_cells = lambda a: (i for i,v in ndenumerate(a) if v=='d')
      

      这也适用于二维以上的数组。

      【讨论】:

        猜你喜欢
        • 2014-03-17
        • 1970-01-01
        • 1970-01-01
        • 2013-07-22
        • 2020-06-17
        • 1970-01-01
        • 1970-01-01
        • 2017-05-24
        • 2023-03-29
        相关资源
        最近更新 更多