4

昨日、2 次元配列をトラバースし、「d」とマークされたセルの場所を見つける必要があるゲームに取り組んでいました (セルは、空白の場合は「-」、ダーティの場合は「d」で表されます)。

2 つの 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')

しかし、2 番目の応答では、間違ったデータが返されます (つまり、「d」セルが見つかりません)。2 番目が 1 番目と等しくないという、私が見落としている単純な何かがあるに違いありませんが、それはわかりません。私が解決しようとした本当の質問はこれです:私の最初の試みがジェネレーターを返すようにする簡単な方法はありますか?

4

3 に答える 3

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)andループを交換しました。enumerate(row)row

この場合、代わりに を使用して、ジェネレーター式の代わりにジェネレーター関数を使用する方が簡単な場合があります。yielddirty_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

これはまったく同じ効果がありますが、おそらくより読みやすくなります。

于 2013-07-01T15:19:51.910 に答える
3

元の関数をジェネレーターにきれいに変換するには、必要なのはyieldではなくステートメントですreturn(または、特定のケースでは ではなくappend)。元の式の方がはるかに読みやすいため、ジェネレーター式のバージョンよりもこのバージョンをお勧めします。

def find_dirty_cells(board):
    for enum, row in enumerate(board):
        for enumrow, cell in enumerate(row):
            if cell == 'd':
                yield (enum, enumrow)
于 2013-07-01T15:20:16.743 に答える
1

を使用してこれを行う簡単な方法は次のnumpy.ndenumerate()とおりです。

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

これは、2 次元を超える配列でも機能します。

于 2013-07-01T15:34:21.493 に答える