1

我需要生成一个迭代器,它将迭代 Python 2D 数组并在 MxN 邻域中产生每个项目及其周围的所有项目。

例如,给定棋盘模式中的 0 和 1 列表,我需要一个迭代器对象,它会产生一个 3x3 邻域,例如:

[0,1,0],
[1,0,1],
[0,1,0]

注意产量不需要是另一个数组,但如果能够引用具有相对于中心项目的位置/索引的邻居,或者至少相对于彼此,那就太好了。

提前致谢。

编辑:到目前为止,我一直在尝试仅通过索引来做到这一点,即

for x in range(len(S)):
    for y in range(len(S[0])):
        for i in range(-1,2):
            for j in range(-1,2):
                #access neighbour with S[x+i][y+j]
4

2 回答 2

0
board = [
    [1,0,1,0,1],
    [1,0,1,0,1],
    [1,0,1,0,1],
    [1,0,1,0,1],
    [1,0,1,0,1]
]

def clamp(minV,maxV,x):
    if x < minV:
        return minV 
    elif x > maxV:
        return maxV
    else:
        return x

def getNeighbour(grid,startx,starty,radius):
    width = len(grid[starty])
    height = len(grid)
    neighbourhood = []
    for y in range(clamp(0,height,starty-radius),clamp(0,height,starty+radius)+1):
        row = []
        for x in range(clamp(0,width,startx-radius),clamp(0,width,startx+radius)+1):
            if x != startx or (x==startx and  y != starty):
                row.append(grid[y][x])
        neighbourhood.append(row)
    return neighbourhood

例子:

>>> pprint(getNeighbour(board, 0, 0, 1))
[0]
[1, 0] (expected)
>>> pprint(getNeighbour(board, 2, 2, 1))
[0, 1, 0]
[0, 0]
[0, 1, 0] (expected)
>>> 

使用以下列表解决性能方面的问题:

board = [[1,0]*2000]*1000

运行时间基本上与板是 10x10 相同

于 2013-06-24T08:01:40.937 回答
0

您通常可以通过将元素存储在一维列表中并根据数组的逻辑宽度和高度计算偏移量来快速访问二维数组。它通常可以简化计算和边界检查,它们只需要在内部处理一维。

class Board(object):
    def __init__(self, width, height):
        self.height = height
        self.width = width
        self.size = width*height
        self.board = [i%2 for i in xrange(self.size)] # checkerboard init

    def __getitem__(coords):
        """ get board[x, y] """
        offset = coords[1]*self.width + coords[0]
        return self.board[offset]

    def __setitem__(coords, value):
        """ set board[x, y] = value """
        offset = coords[1]*self.width + coords[0]
        self.board[offset] = value

    def __str__(self):
        lines = []
        for y in xrange(self.height):
            offset = y*self.width
            row = self.board[offset:offset+self.width]
            lines.append(','.join(str(v) for v in row))
        return ',\n'.join(lines)

    def neighbourhood(self, x, y):
        position = y*self.width + x
        for offset in [
            position-self.width-1, position-self.width, position-self.width+1,
            position-1,                                 position+1,
            position+self.width-1, position+self.width, position+self.width+1]:
            if -1 < offset < self.size:
                yield self.board[offset]

board = Board(5, 5)
print board
print
print [value for value in board.neighbourhood(0, 0)]
print [value for value in board.neighbourhood(2, 2)]

输出:

0,1,0,1,0,
1,0,1,0,1,
0,1,0,1,0,
1,0,1,0,1,
0,1,0,1,0

[1, 0, 1, 0]
[0, 1, 0, 1, 1, 0, 1, 0]
于 2013-06-24T11:01:24.770 回答