2009-08-22 4 views
6

Ich habe ein 3D-Array in Python und ich muss über alle Cubes im Array iterieren. Das heißt, für alle (x,y,z) in die Dimensionen des Arrays ich den Cube zugreifen müssen:Pythonische Art der Iteration über 3D-Array

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

Das Array ist ein Numpy Array, obwohl das nicht wirklich notwendig. Ich fand es einfach, die Daten mit einem Einzeiler unter Verwendung von numpy.fromfile() zu lesen.

Gibt es noch mehr Pythonic-Methode, um über diese als die folgenden zu iterieren? Das sieht einfach so aus wie C mit Python-Syntax.

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

Wird dies von http beantwortet werden : //stackoverflow.com/questions/1280667/in-python-is-there-an-easier-way-to-write-6-nested-for-loops? – tom10

+0

Das wäre der Bereich (...- 1), hier ... – EOL

+0

Eigentlich ja @ tom10, es beantwortet die Frage –

Antwort

14

Werfen Sie einen Blick auf itertools, vor allem itertools.product. Sie können die drei Schleifen in eine mit

import itertools 

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

komprimieren können Sie auch den Würfel auf diese Weise erstellen:

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

und die Offsets

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

durch einen einfachen Zusatz hinzuzufügen, die würde zu übersetzen in cube + (x,y,z) in Ihrem Fall. Die sehr kompakte Version des Codes würde

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) 

bearbeiten sein: itertools.product das Produkt über die verschiedenen Argumente macht, also itertools.product(a,b,c), also muss ich passieren map(xrange, ...) mit als *map(...)

+0

Das ergibt den Fehler: ValueError: Form-Mismatch: Objekte können nicht zu einer einzigen Form gesendet werden –

+0

... Aber '' (x, y, z) 'anstelle von' offset' in Ihrem Beispiel behebt, dass –

+0

\ * seufz * immer testen Sie Ihren Code vor dem Aufstellen –

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