2009-08-22 30 views
6

Tôi có một mảng 3D trong Python và tôi cần phải lặp qua tất cả các khối trong mảng. Đó là, cho tất cả (x,y,z) trong kích thước của mảng tôi cần phải truy cập vào các khối:Cách Pythonic lặp qua mảng 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)] 

Mảng là một mảng NumPy, mặc dù đó không phải là thực sự cần thiết. Tôi chỉ thấy rất dễ đọc dữ liệu bằng một lớp lót sử dụng numpy.fromfile().

Có cách nào khác để Pythonic lặp qua những thứ này không? Điều đó chỉ đơn giản là giống như C bằng cách sử dụng cú pháp 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

Liệu điều này được trả lời bằng http : //stackoverflow.com/questions/1280667/in-python-is-there-an-easier-way-to-write-6-nested-for-loops? – tom10

+0

Đó sẽ là phạm vi (...- 1), ở đây ... – EOL

+0

Thực ra, có @ tom10, nó trả lời câu hỏi –

Trả lời

14

Có một cái nhìn tại itertools, đặc biệt là itertools.product. Bạn có thể nén ba vòng thành một với

import itertools 

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

Bạn cũng có thể tạo ra các hình khối theo cách này:

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

và thêm offsets bởi một bổ sung đơn giả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]]) 

mà sẽ đến dịch sang số cube + (x,y,z) trong trường hợp của bạn. Phiên bản rất nhỏ gọn của mã của bạn sẽ

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) 

Sửa: itertools.product làm cho sản phẩm qua các đối số khác nhau, tức là itertools.product(a,b,c), vì vậy tôi phải vượt qua map(xrange, ...) với như *map(...)

+0

Điều này dẫn đến lỗi: ValueError: hình dạng không khớp: đối tượng không thể phát sóng thành một hình –

+0

... Tuy nhiên, bằng cách sử dụng '(x, y, z)' thay vì 'offset' trong ví dụ của bạn, hãy sửa rằng –

+0

\ * sigh * luôn kiểm tra mã của bạn trước khi đặt nó lên –

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]) 
Các vấn đề liên quan