2009-08-22 16 views
6

Tengo una matriz 3D en Python y necesito iterar sobre todos los cubos de la matriz. Es decir, para todos (x,y,z) en las dimensiones de la matriz necesito para acceder al cubo:Manera pitónica de iterar sobre una matriz 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 matriz es una matriz Numpy, aunque eso no es realmente necesario. Me pareció muy fácil leer los datos con un solo trazador usando numpy.fromfile().

¿Hay alguna forma más pitonica de iterar sobre estos que la siguiente? Eso simplemente se ve como C usando la sintaxis de 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

Será este respondidas por http : //stackoverflow.com/questions/1280667/in-python-is-there-an-easier-way-to-write-6-nested-for-loops? – tom10

+0

Ese sería el rango (...- 1), aquí ... – EOL

+0

En realidad, sí @ tom10, responde a la pregunta –

Respuesta

14

Tenga una mirada en itertools, especialmente itertools.product. Puede comprimir los tres bucles en uno con

import itertools 

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

También puede crear el cubo de esta manera:

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

y añadir las compensaciones por una simple adición

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

lo que a traducir a cube + (x,y,z) en su caso. La versión compacta de su código sería

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) 

Editar: itertools.product hace que el producto a través de los diferentes argumentos, es decir itertools.product(a,b,c), así que tengo que pasar map(xrange, ...) con tan *map(...)

+0

Esto da como resultado el error: ValueError: forma no coinciden: los objetos no se pueden transmitir a una sola forma –

+0

... Sin embargo, al usar '(x, y, z)' en lugar de 'offset' en su ejemplo corrige que –

+0

\ * suspiro * siempre pruebe el código antes de ponerlo –

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