2009-10-25 56 views
8

我有一個列表清單,類似於確定細胞二維列表的鄰居

[[1, 2, 3,],[4, 5, 6,],[7, 8, 9]]

圖形的方式直觀的:

1 2 3 
4 5 6 
7 8 9 

我正在尋找一個優雅的方式來檢查電池,水平,垂直和對角線的鄰居的價值。例如,[0] [2]的鄰居是[0] [1],[1] [1]和[1] [2]或數字2,5,6。

現在我明白了我可能只是做一個暴力破解攻擊檢查每一個值一拉:

[i-1][j] 
[i][j-1] 
[i-1][j-1] 
[i+1][j] 
[i][j+1] 
[i+1][j+1] 
[i+1][j-1] 
[i-1][j+1] 

但是那很容易,我想我可以看到一些更優雅的方式瞭解更多信息。

+0

你想要得到的指數或值是多少?你想要一個可以對每個索引進行隨機訪問的函數,或者是一個返回(val,neighbors_of_val)對列表的函數嗎? - 剛開指數是一個優雅的解決方案過於簡單,但你真正想要做什麼可能是更有趣 – 2009-10-25 13:48:01

+1

要麼或 - 我故意留下這個問題相當普遍所以人們不會感到約束。 – 2009-10-25 13:49:39

回答

15
# Size of "board" 
X = 10 
Y = 10 

neighbors = lambda x, y : [(x2, y2) for x2 in range(x-1, x+2) 
           for y2 in range(y-1, y+2) 
           if (-1 < x <= X and 
            -1 < y <= Y and 
            (x != x2 or y != y2) and 
            (0 <= x2 <= X) and 
            (0 <= y2 <= Y))] 

>>> print(neighbors(5, 5)) 
[(4, 4), (4, 5), (4, 6), (5, 4), (5, 6), (6, 4), (6, 5), (6, 6)] 

如果這被認爲是乾淨的,我不知道,但是這一個班輪讓你通過遍歷所有的鄰居他們並丟棄任何邊緣情況。

+0

如果「板」是什麼'10201x10201'? – FaCoffee 2015-11-22 19:00:17

+0

@ CF84:然後常量'X'和'Y'需要分配不同的值。你有關於這個問題 - 你有什麼意見? – martineau 2017-01-26 21:27:22

+0

@CDspace編輯如何偏離帖子的原意?如果你的意思是單線,它仍然可以寫在一個具有正常功能的行上。而且,自從上一次編輯以來,它一直都不是單行的。至少大寫的X和Y變量應該改變,因爲它們很難被發現。 – skrx 2017-02-28 23:41:34

1

這裏是你的清單:

(x - 1, y - 1) (x, y - 1) (x + 1, y - 1) 
(x - 1, y)  (x, y)  (x + 1, y) 
(x - 1, y + 1) (x, y + 1) (x + 1, y + 1) 

左右(X,Y)的水平鄰居是(x +/- 1,Y)。

垂直鄰居是(x,y +/- 1)。

對角線的鄰居是(x +/- 1,y +/- 1)。

這些規則適用於無限矩陣。 爲了確保鄰居適合有限矩陣,如果初始(x,y)位於邊緣,只需對鄰居的座標(矩陣大小)再應用一個限制即可。

2

有沒有更簡單的方法來做到這一點。如果你真的想你可以創建一個函數:

def top(matrix, x, y): 
    try: 
     return matrix[x][y - 1]; 
    except IndexError: 
     return None 
+0

'除了IndexError' – u0b34a0f6ae 2009-10-25 17:17:05

+0

@ Kaizer.se:謝謝,不知道它是哪一個懶得看它還是試試吧。 – 2009-10-25 18:06:59

+0

+1這不是一個完整的解決方案,但自認爲有趣的可能是相當搜索鄰居Python化的方式 - 這是EAFP – u0b34a0f6ae 2009-10-25 19:38:19

0
>>> import itertools 
>>> def sl(lst, i, j): 
    il, iu = max(0, i-1), min(len(lst)-1, i+1) 
    jl, ju = max(0, j-1), min(len(lst[0])-1, j+1) 
    return (il, iu), (jl, ju) 

>>> lst = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] 
>>> tup = 0, 2 
>>> [lst[i][j] for i, j in itertools.product(*sl(lst, *tup)) if (i, j) != tup] 
[2, 5, 6] 

我不知道它是如何優雅似乎你,但它似乎工作W/O任何硬編碼。

3
for x_ in range(max(0,x-1),min(width,x+2)): 
    for y_ in range(max(0,y-1),min(height,y+2)): 
    if (x,y)==(x_,y_): continue 
    # do stuff with the neighbours 

>>> a=[[1, 2, 3], [4, 5, 6], [7, 8, 9]] 
>>> width=height=3 
>>> x,y=0,2 
>>> for x_ in range(max(0,x-1),min(width,x+2)): 
... for y_ in range(max(0,y-1),min(height,y+2)): 
...  if (x,y)==(x_,y_): continue 
...  print a[x_][y_] 
... 
2 
5 
6 
0

這將生成所有索引:

def neighboring(array): 
    nn,mm = len(array), len(array[0]) 
    offset = (0,-1,1) # 0 first so the current cell is the first in the gen 
    indices = ((i,j) for i in range(nn) for j in range(mm)) 
    for i,j in indices: 
     all_neigh = ((i+x,j+y) for x in offset for y in offset) 
     valid = ((i,j) for i,j in all_neigh if (0<=i<nn) and (0<=j<mm)) # -1 is a valid index in normal lists, but not here so throw it out 
     yield valid.next(), valid ## first is the current cell, next are the neightbors 

for (x,y), neigh in neighboring(l): 
    print l[x][y], [l[x][y] for x,y in neigh] 
0

也許你正在檢查一個數獨箱。如果盒子是爲n×n和當前單元格(X,Y)開始檢查:

startingRow = x/n * n; 
startingCol = y/ n * n 
8

MB ...

from itertools import product, starmap 

x, y = (8, 13) 
cells = starmap(lambda a,b: (x+a, y+b), product((0,-1,+1), (0,-1,+1))) 

// [(8, 12), (8, 14), (7, 13), (7, 12), (7, 14), (9, 13), (9, 12), (9, 14)] 
print(list(cells)[1:]) 
+1

我不明白這個答案,我跑了它在Python 2.7問題的例子一起。 – octopusgrabbus 2012-07-14 22:34:37

5

假設你有一個方陣:

from itertools import product 

size = 3 

def neighbours(cell): 
    for c in product(*(range(n-1, n+2) for n in cell)): 
     if c != cell and all(0 <= n < size for n in c): 
      yield c 

使用itertools.product和感謝Python的yield expressionstar operator,功能相當dry但仍足以可讀。

鑑於3矩陣大小,然後你可以(如果需要)收集的鄰居在list

>>> list(neighbours((2,2))) 
[(1, 1), (1, 2), (2, 1)] 

什麼功能也可以看作如下:

Function visualization

0

如果有人好奇的替代方法可以選擇直接(非對角線)的鄰居,在這裏你去:

neighbors = [(x+a[0], y+a[1]) for a in 
        [(-1,0), (1,0), (0,-1), (0,1)] 
        if ((0 <= x+a[0] < w) and (0 <= y+a[1] < h))]