2009-10-25 7 views
8

Ich habe eine Liste von Listen, so etwas wieBestimmen der Nachbarn der Zelle zweidimensionale Liste

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

Grafisch dargestellt als:

1 2 3 
4 5 6 
7 8 9 

Ich bin für einen eleganten Ansatz sucht den Wert der Nachbarn einer Zelle, horizontal, vertikal und diagonal zu überprüfen. Zum Beispiel sind die Nachbarn von [0] [2] [0] [1], [1] [1] und [1] [2] oder die Zahlen 2, 5, 6.

Jetzt erkenne ich konnte nur einen Brute-Force-Angriff tun jeden Wert a la Überprüfung:

[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] 

Aber das ist einfach, und ich dachte, ich sah einige elegantere Ansätze mehr lernen können.

+0

Möchten Sie die Indizes oder die Werte erhalten? Und wollen Sie eine Funktion, die zufälligen Zugriff auf jeden Index oder eine Funktion, die eine Liste von (val, Nachbarn_von_val) -Paaren zurückgibt, tun können? - Einfach die Indizes zu bekommen ist zu einfach für eine elegante Lösung, aber was Sie wirklich tun wollen, könnte interessanter sein. –

+1

Entweder oder - Ich habe diese Frage bewusst so allgemein gehalten, dass die Leute sich nicht eingeschränkt fühlen würden. –

Antwort

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)] 

Ich weiß nicht, ob diese sauber betrachtet wird, aber diese Einzeiler gibt Ihnen alle Nachbarn von iterieren sie und verwerfen alle Randfälle.

+0

Was ist, wenn das "Brett" '10201x10201' ist? – FaCoffee

+0

@ CF84: Dann müssten den Konstanten 'X' und' Y' andere Werte zugewiesen werden. Hast du ein Problem in diesem Zusammenhang? Was ist dein Standpunkt? – martineau

+0

@CDspace Wie unterscheidet sich die Bearbeitung von der ursprünglichen Absicht des Posts? Wenn Sie den One-Liner meinen, kann er immer noch auf einer Zeile mit einer normalen Funktion geschrieben werden. Außerdem war es seit dem letzten Schnitt sowieso kein One-Liner mehr. Zumindest die Großbuchstaben X und Y sollten geändert werden, da sie schwer zu erkennen sind. – skrx

1

Hier ist die Liste:

(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) 

So sind die horizontalen Nachbarn von (x, y) (x +/- 1, y).

Die vertikalen Nachbarn sind (x, y +/- 1).

Diagonale Nachbarn sind (x +/- 1, y +/- 1).

Diese Regeln gelten für eine unendliche Matrix. Um sicherzustellen, dass die Nachbarn in eine endliche Matrix passen, wenn der Anfang (x, y) am Rand ist, wenden Sie einfach eine weitere Einschränkung auf die Koordinaten von Nachbarn an - die Matrixgröße.

2

Es gibt keinen saubereren Weg, dies zu tun. Wenn Sie wirklich wollen, könnten Sie eine Funktion erstellen:

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

'außer IndexError' – u0b34a0f6ae

+0

@ Kaizer.se: Danke, war nicht sicher, welcher es war und zu faul, um es zu suchen oder es zu versuchen. –

+0

+1 das ist keine vollständige Lösung, aber interessant, da das eine ziemlich pythonische Art sein könnte, nach Nachbarn zu suchen - es ist EAFP – u0b34a0f6ae

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] 

Ich weiß nicht, wie elegant es dir scheint, aber es scheint, w/o jeder Hartcodierung zu arbeiten.

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

Dies erzeugt alle Indizes:

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

vielleicht haben Sie ein Sudoku-Box sind zu überprüfen. Wenn die Box nxn und aktuelle Zelle ist (x, y) Prüfung starten:

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

Ich verstehe diese Antwort nicht, und ich habe sie zusammen mit dem Beispiel der Frage in Python 2.7 ausgeführt. – octopusgrabbus

5

Sie haben eine quadratische Matrix Unter der Annahme:

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 

Mit itertools.product und dank Python yield expression und star operator ist die Funktion ziemlich dry aber noch lesbar genug.

eine Matrixgröße von 3 gegeben, können Sie dann (falls erforderlich) sammeln die Nachbarn in einem list:

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

Was die Funktion wie folgt visualisiert werden nicht können:

Function visualization

0

Wenn jemand neugierig auf alternative Möglichkeit ist, direkt (nicht diagonal) Nachbarn zu wählen, gehen Sie hier:

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))] 
Verwandte Themen