2D Python列表中每个项目的迭代器及其直接m by n邻域

时间:2013-06-24 07:40:36

标签: python list iterator

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

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

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

N.B。 yield不需要是另一个数组,但是能够引用具有相对于中心项的位置/索引的邻居,或者至少相对于彼此是很好的。

提前致谢。

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

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]

2 个答案:

答案 0 :(得分: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

基本相同

答案 1 :(得分: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]