2009-10-25 12 views
8

Ho una lista di liste, qualcosa comeDeterminazione dei vicini della cella elenco bidimensionale

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

rappresentato graficamente come:

1 2 3 
4 5 6 
7 8 9 

sto cercando un approccio elegante per controllare il valore dei vicini di una cella, in senso orizzontale, verticale e diagonale. Ad esempio, i vicini di [0] [2] sono [0] [1], [1] [1] e [1] [2] o i numeri 2, 5, 6.

Ora mi rendo conto che potrebbe fare solo un attacco di forza bruta controllando ogni valore a la:

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

Ma questo è facile, e ho pensato che posso imparare di più vedendo alcuni più eleganti approcci.

+0

Vuoi ottenere gli indici oi valori? E vuoi una funzione che possa fare un accesso casuale su ogni indice o una funzione che restituisca una lista di coppie (val, neighbors_of_val)? - Ottenere gli indici è troppo semplice per una soluzione elegante, ma quello che vuoi veramente fare potrebbe essere più interessante –

+1

O o - Ho lasciato deliberatamente questa domanda in modo abbastanza generale, così le persone non si sentirebbero costrette. –

risposta

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

Non so se questo è considerato pulito, ma questo one-liner ti dà tutti i vicini di iterare su loro e scartando ogni caso limite.

+0

Cosa succede se la "scheda" è "10201x10201"? – FaCoffee

+0

@ CF84: quindi le costanti 'X' e' Y' dovrebbero avere valori diversi ad esse assegnati. Hai un problema in merito? Qual è il tuo punto? – martineau

+0

@CDspace come devia la modifica dall'intenzione originale del post? Se intendi l'one-liner, può ancora essere scritto su una riga con una funzione normale. Inoltre, non è stato un one-liner in ogni caso dal precedente modifica. Almeno le variabili X e Y maiuscole dovrebbero essere cambiate, poiché sono difficili da individuare. – skrx

1

Ecco l'elenco:

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

Così i vicini orizzontali di (x, y) sono (x +/- 1, y).

I vicini verticali sono (x, y +/- 1).

I vicini diagonali sono (x +/- 1, y +/- 1).

Queste regole si applicano a una matrice infinita. Per assicurarsi che i vicini si inseriscano in una matrice finita, se l'iniziale (x, y) si trova sul bordo, basta applicare un'altra restrizione alle coordinate dei vicini - la dimensione della matrice.

2

Non c'è un modo più semplice per farlo. Se si vuole veramente è possibile creare una funzione:

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

'except IndexError' – u0b34a0f6ae

+0

@ Kaizer.se: Grazie, non ero sicuro di quale fosse e troppo pigro per cercarlo o provarlo. –

+0

+1 questa non è una soluzione completa, ma interessante dato che potrebbe essere un modo piuttosto Python per cercare i vicini: è 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] 

Non so quanto elegante che sembra a voi, ma sembra funzionare w/o qualsiasi hard-codifica.

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

Questo genera tutti gli indici:

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

forse si sta verificando una scatola di sudoku. Se la casella è nxn e cella corrente è (x, y) avviare il controllo:

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

Non capisco questa risposta, e l'ho eseguita insieme all'esempio della domanda in Python 2.7. – octopusgrabbus

5

si Supponendo hanno una matrice quadrata:

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 

Utilizzando itertools.product e grazie a Python di yield expression e star operator, la funzione è abbastanza dry ma ancora abbastanza leggibile.

Data una dimensione della matrice di 3, si può quindi (se necessario) raccogliere i vicini in un list:

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

Che la funzione non può essere visualizzato come segue:

Function visualization

0

Se qualcuno è curioso di un modo alternativo di scegliere i vicini diretti (non diagonali), ecco qui:

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