遍历多维数组的元素,并找到没有numpy或imports的邻居

2024-05-20 03:42:50 发布

您现在位置:Python中文网/ 问答频道 /正文

在python中,如何在不使用numpy或任何导入(仅使用递归)的情况下迭代多维数组的元素并查找其邻居?例如,minesweeper_board = [[[0, 'b'], [0, 0], [0, 0]], [[0, 0], [0, 0], ['b', 0]], [[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]]]'b'标记炸弹,我想更新每个零周围的炸弹数量(就像在扫雷游戏中一样)


Tags: 标记numpyboard游戏元素数量情况数组
2条回答

我遇到了同样的问题,我不得不为numpy.exp()函数做一个替代,因为它可以遍历n维列表。但我在网上找不到任何解决方案,这是我能找到的唯一stackoverflow线程,但没有找到解决方案。所以我自己做了一个函数,使用递归遍历n维列表。 iterate(list)函数接受一个n维列表,并使用递归对其进行迭代

import math

def iterate(list1):
    for x in range(len(list1)):
        if isinstance(list1[x], list):
            iterate(list1[x])
        else:
            list1[x]=math.exp(list1[x]) # Manipulate the elements as you require

list2 = [[[2, 1], [3, 5], [6, 7]], [[8, 9], [6, 7], [12, 5]], [[3, 7], [2, 2], [3, 4]], [[5, 6], [7, 8], [9, 8]]]
iterate(list2)
print(list2)

此特定方法将把n维列表1中的每个元素x更改为e^x

输出:

[[[7.38905609893065, 2.718281828459045], [20.085536923187668, 148.4131591025766], [403.4287934927351, 1096.6331584284585]], [[2980.9579870417283, 8103.083927575384], [403.4287934927351, 1096.6331584284585], [162754.79141900392, 148.4131591025766]], [[20.085536923187668, 1096.6331584284585], [7.38905609893065, 7.38905609893065], [20.085536923187668, 54.598150033144236]], [[148.4131591025766, 403.4287934927351], [1096.6331584284585, 2980.9579870417283], [8103.083927575384, 2980.9579870417283]]]

我建议为每一行/列对建立一个指向相邻坐标的链接字典。在程序的许多部分中,当您需要计算位置周围的值时,这可以用作间接寻址:

minesweeper_board = [ [ [0, 'b'], [0, 0], [0, 0]   ],
                      [ [0, 0],   [0, 0], ['b', 0] ],
                      [ [0, 0],   [0, 0], [0, 0]   ],
                      [ [0, 0],   [0, 0], [0, 0]   ]
                    ]

rows      = 4
cols      = 3
offsets   = [(-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1)]

def inBoard(r,c): return r in range(rows) and c in range(cols)

def getNeighbours(r,c): return [(r+v,c+h) for v,h in offsets if inBoard(r+v,c+h)] 

links = { (r,c):getNeighbours(r,c) for r in range(rows) for c in range(cols) }

使用链接字典:

for (r,c),neighbours in links.items():
    bombCount = sum('b' in minesweeper_board[nr][nc] for nr,nc in neighbours) 
    if bombCount:
        print(f"there are {bombCount} bombs near {(r,c)}")

输出:

there are 2 bombs near (0, 1)
there are 1 bombs near (0, 2)
there are 1 bombs near (1, 0)
there are 2 bombs near (1, 1)
there are 1 bombs near (2, 1)
there are 1 bombs near (2, 2)

[编辑]多维电路板的通用化

我最初误解了这个问题,但可以通过创建递归n维访问函数来推广上述解决方案。Python的列表或列表结构不适合通过多个维度进行索引:board[1][2][3]与numpy的board[1,2,3]相比有点笨拙,但我们可以使用函数(或通过创建一个全新的类,这将需要更多的工作)来弥补这一点:

# access the value at a specific coordinate
def getCell(board,pos,*rest):
    return getCell(board[pos],*rest) if rest else board[pos]

# assign the value at a specific coordinate
def setCell(board,pos,*rest,value):
    if rest : setCell(board[pos],*rest,value=value)
    else:     board[pos] = value 

# get the values of the cell and all its neighbours at a coordinate 
def getNeighbours(board,pos,*rest):
    for nPos in (pos-1,pos,pos+1):
        if nPos not in range(len(board)): continue
        if not rest: yield board[nPos]; continue
        for value in getNeighbours(board[nPos],*rest):
            yield value

# iterate over the whole board returning coordinates and values    
def iterate(board):
    if not isinstance(board,list): yield ([],board); return
    for i,subBoard in enumerate(board):
        for coord,value in iterate(subBoard):
            yield ([i] + coord,value)

# assign counts of nearby bombs to each coordinate that is not a bomb
def countBombs(board):
    for coord,value in iterate(board):
        if value == "b": continue
        count = [*getNeighbours(board,*coord)].count("b")
        setCell(board,*coord,value=count)

输出:

minesweeper_board = [ [ [0, 'b'], [0, 0], [0, 0]   ],
                      [ [0, 0],   [0, 0], ['b', 0] ],
                      [ [0, 0],   [0, 0], [0, 0]   ],
                      [ [0, 0],   [0, 0], [0, 0]   ]
                    ]

countBombs(minesweeper_board)
print(minesweeper_board)

[
   [ [1, 'b'], [2, 2], [1, 1]   ],
   [  [1, 1],  [2, 2], ['b', 1] ],
   [  [0, 0],  [1, 1], [1, 1]   ],
   [  [0, 0],  [0, 0], [0, 0]   ]
]


getCell(minesweeper_board,1,2,0) # 'b'
getCell(minesweeper_board,1,1,1) # 2

相关问题 更多 >