处理python中2D列表边界检查的最佳方法?

时间:2019-02-26 22:50:01

标签: python python-3.x

我有一个如下的2D列表,如果周围单元格为0,我想将单元格值从1更改为0 喜欢

from
[
  [1, 0, 1, 0, 1],
  [0, 0, 1, 0, 0],
  [0, 0, 0, 0, 0],
  [1, 0, 1, 0, 1],
  [0, 0, 0, 0, 0],
  [1, 0, 1, 0, 1],
]
To
[
  [0, 0, 1, 0, 0],
  [0, 0, 1, 0, 0],
  [0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0],
]

我想我可以使用8个if / else逻辑来检查,但是想知道是否有更好或更干净的方法吗?

4 个答案:

答案 0 :(得分:1)

我将使用python生成器获取有效的邻居,并使用all检查所有邻居是否为零。

def update_cell(grid):
    if not grid or not grid[0]:
        return
    m, n = len(grid), len(grid[0])

    def is_valid(i, j):
        return 0 <= i < m and 0 <= j < n

    def neighbors(i, j):
        for di, dj in [(0, 1), (0, -1), (1, 0), (-1, 0), (-1, 1), (-1, -1), (1, -1), (1, 1)]:
            ni, nj = i+di, j+dj
            if is_valid(ni, nj):
                yield ni, nj

    for i in range(m):
        for j in range(n):
            if grid[i][j] and all(not grid[ni][nj] for ni, nj in neighbors(i, j)):
                grid[i][j] = 0


if __name__ == "__main__":

    grid = [
        [1, 0, 1, 0, 1],
        [0, 0, 1, 0, 0],
        [0, 0, 0, 0, 0],
        [1, 0, 1, 0, 1],
        [0, 0, 0, 0, 0],
        [1, 0, 1, 0, 1],
    ]

    update_cell(grid)

    print(grid)

   # prints
   #[[0, 0, 1, 0, 0], 
   # [0, 0, 1, 0, 0], 
   # [0, 0, 0, 0, 0], 
   # [0, 0, 0, 0, 0], 
   # [0, 0, 0, 0, 0], 
   # [0, 0, 0, 0, 0]]

答案 1 :(得分:0)

求和该问题点周围的3x3列表。如果总和为1(中心单元格的值),则将其设置为0

要选择3x3细分,您可以

  • 迭代所需的3x3切片。
  • 使用切片切片为每张支票创建一个新的3x3分段。
  • 将您的列表转换为NumPy 2D数组; NumPy具有很好的切片功能。

答案 2 :(得分:0)

我会写if,但是像其他答案中那样生成邻居是很优雅的。

如果您可以更改数据结构 并且需要速度,则可以使用虚影单元格。

像这样用零包围网格:

       0 0 0 0
1 2    0 1 2 0
4 5    0 4 5 0
       0 0 0 0

然后您可以从1..n-1进行迭代,并始终拥有所有邻居

答案 3 :(得分:0)

一种方法是:

def neighbors(m,r,c):
    return sum((
        sum(m[r-1][max(0,c-1):c+2]) if 0 <= r-1 < len(m) else 0,
        sum(m[r  ][max(0,c-1):c+2]) if 0 <= r   < len(m) else 0,
        sum(m[r+1][max(0,c-1):c+2]) if 0 <= r+1 < len(m) else 0,
    )) - m[r][c]

它采用(r,c)元素周围的3x3平方和,然后减去(r,c)处的值。

有多种方法可以根据喜好进行清理,例如:

def neighbors(m,r,c):
    return sum(
        sum(m[x][max(0,c-1):c+2]) for x in [r-1,r,r+1] if 0 <= x < len(m)
    ) - m[r][c]

这里唯一真正聪明的事情是,您可以使用切片来规避越界错误。因此x = [1,2,3]; print(x[100:200])只会打印一个空列表,而不会打印IndexError

我是否应该使用此代码,而不是简单的嵌套for循环? 几乎没有。