如何检查数组中的边界重复项

时间:2018-07-10 14:09:57

标签: arrays python-3.x flood-fill

如果我有一个包含整数的数组组成的数组

arr[0] = [0, 0, 1, 1, 1, 0, -1]    0
arr[1] = [1, 0, 0, 0, 1, -1, 0]    1
arr[2] = [0, 0, 0, 1, 1, -1, 0]    2

          0  1  2  3  4  5   6

例如,我想检查在水平和垂直方向上有多少个相同的整数彼此相邻。例如,如果我选择坐标(1、2),它是0。我希望它输出数字8。因为有8个连续的零,所有零彼此相邻。 我怎么能写一个恰好做到这一点的函数?

我已经在Python中尝试了以下两个功能

print checkLoc(1, 2)

def checkLoc(x, y):
    amt = 0
    n = arr[y][x]
    checkPos(x, y, n)
    return amt

def checkPos(x, y, n):
    amt += 1
    if arr[y - 1][x] == n:
        checkPos(x, y - 1, n)
    if arr[y + 1][x] == n:
        checkPos(x, y + 1, n)
    if arr[y][x - 1] == n:
        checkPos(x - 1, y, n)
    if arr[y][x + 1] == n:
        checkPos(x + 1, y, n)

我希望这能奏效,但不能奏效。我已经对此进行了一些试验,因为我根本无法弄清楚,所以我将不胜感激。 谢谢。

2 个答案:

答案 0 :(得分:1)

在递归方法中,您没有基础案例,也无法防止下标超出范围。您也没有采取任何措施阻止多次访问同一位置。以下内容借助帮助数据结构来跟踪您访问过的位置,从而实现了您似乎试图使用的逻辑。请注意,我将arr设置为局部变量,因为我不愿意在没有充分理由的情况下使用全局变量:

def checkPos(arr,visited,i,j,v):
    visited[i][j] = True
    if arr[i][j] != v:
        return 0
    else:
        count = 1 #current position
        if i > 0 and not visited[i-1][j]:
            count += checkPos(arr,visited,i-1,j,v)
        if i < len(arr)-1 and not visited[i+1][j]:
            count += checkPos(arr,visited,i+1,j,v)
        if j > 0 and not visited[i][j-1]:
            count += checkPos(arr,visited,i,j-1,v)
        if j < len(arr[0])-1 and not visited[i][j+1]:
            count += checkPos(arr,visited,i,j+1,v)
        return count

def checkLoc(arr, x, y):
    m = len(arr) # number of rows
    n = len(arr[0]) #number of columns
    visited = [[False]*n for _ in range(m)]
    v = arr[y][x] #value at the position
    return checkPos(arr, visited, y, x, v)

#test:

arr =[[0, 0, 1, 1, 1, 0, -1],
      [1, 0, 0, 0, 1, -1, 0],
      [0, 0, 0, 1, 1, -1, 0]]

counts = [[checkLoc(arr,j,i) for j in range(7)] for i in range(3)]
print('\n'.join(str(row) for row in counts))

输出符合预期:

[8, 8, 6, 6, 6, 1, 1]
[1, 8, 8, 8, 6, 2, 2]
[8, 8, 8, 6, 6, 2, 2]

答案 1 :(得分:1)

您可以尝试使用洪水填充算法来解决。考虑一下您的阵列。

arr = np.array([[0, 0, 1, 1, 1, 0, -1],
                [1, 0, 0, 0, 1, -1, 0],
                [0, 0, 0, 1, 1, -1, 0]])

泛滥算法,例如

def fillin(arr, x, y, new_value):
    """Graphically fills in `new_value` on location (x, y) replacing all
    adjacent values currently located there."""
    old_value = arr[y, x]
    n, m = arr.shape
    arr[y, x] = new_value
    if y > 0 and arr[y-1, x] == old_value:
        fillin(arr, x, y-1, new_value)
    if y < n-1 and arr[y+1, x] == old_value:
        fillin(arr, x, y+1, new_value)
    if x > 0 and arr[y, x-1] == old_value:
        fillin(arr, x-1, y, new_value)
    if x < m-1 and arr[y, x+1] == old_value:
        fillin(arr, x+1, y, new_value)

然后,此算法的作用很简单,例如用其他方法填充(1,2)处的相邻零

>>> fillin(arr, 1, 2, 2)
>>> arr
array([[ 2,  2,  1,  1,  1,  0, -1],
       [ 1,  2,  2,  2,  1, -1,  0],
       [ 2,  2,  2,  1,  1, -1,  0]])

要利用该解决您的问题,对正在调查的单元进行编码

(arr == arr[2, 1]).astype(int)

为您的选择(此处为arr[2, 1] == 0)提供0-1编码,然后在洪水填充前后减去该数组的总和,从而为您提供每个位置的迭代相邻值的数量。让我们定义一种检查一个位置的方法(还将注意不修改输入arr

def check(arr, x, y):
    arr_coded = (arr == arr[y, x]).astype(int)
    sum_before = arr_coded.sum()
    fillin(arr_coded, x, y, 0)
    return sum_before - arr_coded.sum()

根据您的情况,它将给出

>>> check(arr, 1, 2)
8 

还考虑定义一种方法来检查整个输入数组

def check_all(arr):
    n, m = arr.shape
    return np.reshape([check(arr, x, y) for y in range(n) for x in range(m)], (n, m))

这将返回带有“相同的相邻附加值计数”的矩阵

>>> check_all(arr)
array([[8, 8, 6, 6, 6, 1, 1],
       [1, 8, 8, 8, 6, 2, 2],
       [8, 8, 8, 6, 6, 2, 2]])