2009-08-22 6 views
6

Ho un array 3D in Python e ho bisogno di scorrere tutti i cubi dell'array. Cioè, per tutti (x,y,z) nelle dimensioni della matrice ho bisogno di accedere al cubo:Modo iterativo Python per l'array 3D

array[(x + 0, y + 0, z + 0)] 
array[(x + 1, y + 0, z + 0)] 
array[(x + 0, y + 1, z + 0)] 
array[(x + 1, y + 1, z + 0)] 
array[(x + 0, y + 0, z + 1)] 
array[(x + 1, y + 0, z + 1)] 
array[(x + 0, y + 1, z + 1)] 
array[(x + 1, y + 1, z + 1)] 

La matrice è una matrice Numpy, anche se questo non è davvero necessario. Ho appena trovato molto facile leggere i dati con un one-liner usando numpy.fromfile().

C'è qualche altro modo Pythonico per scorrere su questi rispetto al seguente? Sembra semplicemente C usando la sintassi di Python.

for x in range(x_dimension): 
    for y in range(y_dimension): 
     for z in range(z_dimension): 
      work_with_cube(array[(x + 0, y + 0, z + 0)], 
          array[(x + 1, y + 0, z + 0)], 
          array[(x + 0, y + 1, z + 0)], 
          array[(x + 1, y + 1, z + 0)], 
          array[(x + 0, y + 0, z + 1)], 
          array[(x + 1, y + 0, z + 1)], 
          array[(x + 0, y + 1, z + 1)], 
          array[(x + 1, y + 1, z + 1)]) 
+0

Sarà questa risposta da http : //stackoverflow.com/questions/1280667/in-python-is-there-an-easier-way-to-write-6-nested-for-loops? – tom10

+0

Quello sarebbe range (...- 1), qui ... – EOL

+0

In realtà, si @ tom10, risponde alla domanda –

risposta

14

Dai un'occhiata alla itertools, soprattutto itertools.product. È possibile comprimere i tre anelli in uno con

import itertools 

for x, y, z in itertools.product(*map(xrange, (x_dim, y_dim, z_dim)): 
    ... 

È inoltre possibile creare il cubo in questo modo:

cube = numpy.array(list(itertools.product((0,1), (0,1), (0,1)))) 
print cube 
array([[0, 0, 0], 
     [0, 0, 1], 
     [0, 1, 0], 
     [0, 1, 1], 
     [1, 0, 0], 
     [1, 0, 1], 
     [1, 1, 0], 
     [1, 1, 1]]) 

e aggiungere gli offset da una semplice aggiunta

print cube + (10,100,1000) 
array([[ 10, 100, 1000], 
     [ 10, 100, 1001], 
     [ 10, 101, 1000], 
     [ 10, 101, 1001], 
     [ 11, 100, 1000], 
     [ 11, 100, 1001], 
     [ 11, 101, 1000], 
     [ 11, 101, 1001]]) 

che farebbe per traduci in cube + (x,y,z) nel tuo caso. La versione molto compatta del codice sarebbe

import itertools, numpy 

cube = numpy.array(list(itertools.product((0,1), (0,1), (0,1)))) 

x_dim = y_dim = z_dim = 10 

for offset in itertools.product(*map(xrange, (x_dim, y_dim, z_dim))): 
    work_with_cube(cube+offset) 

Edit: itertools.product rende il prodotto sui diversi argomenti, ad esempio itertools.product(a,b,c), quindi devo passare map(xrange, ...) con quanto *map(...)

+0

Ciò risulta nell'errore: ValoreErrore: mancata corrispondenza di forma: gli oggetti non possono essere trasmessi a una singola forma –

+0

... Tuttavia, usando '(x, y, z)' invece di 'offset' nel tuo esempio corregge che –

+0

\ * sigh * verifica sempre il tuo codice prima di metterlo su –

8
import itertools 
for x, y, z in itertools.product(xrange(x_size), 
           xrange(y_size), 
           xrange(z_size)): 
    work_with_cube(array[x, y, z]) 
Problemi correlati