2009-08-22 120 views
6

我在Python中有一个3D数组,我需要迭代数组中的所有多维数据集。也就是说,在阵列的尺寸都(x,y,z)我需要访问立方体:遍历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)] 

该阵列是一个numpy的阵列,尽管这不是真的有必要。我只是发现使用numpy.fromfile()来读取数据非常容易。

是否有更多的Pythonic方式来遍历这些比以下?这看起来像使用Python语法的C。

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

这会不会通过HTTP来回答://stackoverflow.com/questions/1280667/in-python-is-there-an-easier-way-to-write-6-nested-for-loops? – tom10 2009-08-22 14:29:40

+0

这将是范围(...- 1),这里... – EOL 2009-08-22 18:12:39

+0

其实,是@ tom10,它确实回答了问题 – 2009-08-22 18:40:55

回答

14

看一看itertools,尤其是itertools.product。你可以用

import itertools 

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

压缩三个环路成一个你也可以创建多维数据集是这样的:

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

,并通过一个简单的加法添加偏移

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

这将到在你的情况下翻译为cube + (x,y,z)。你的代码非常紧凑的版本将是

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) 

编辑itertools.product使得该产品在不同的参数,即itertools.product(a,b,c),所以我要通过map(xrange, ...)与为*map(...)

+0

这会导致错误: ValueError:形状不匹配:对象无法广播为单个形状 – 2009-08-22 15:41:18

+0

...但是,在你的示例中使用'(x,y,z)'而不是'offset'来修复 – 2009-08-22 15:52:01

+0

\ *叹息*总是在测试代码之前测试你的代码 – 2009-08-22 16:15:10

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