Pythonic地迭代3D数组的方法

9 投票
2 回答
15284 浏览
提问于 2025-04-15 13:48

我在Python中有一个三维数组,我需要遍历数组中的所有立方体。也就是说,对于数组的每一个 (x,y,z) 坐标,我都需要访问这个立方体:

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() 一行代码就能很方便地读取数据。

有没有比下面这种方式更符合Python风格的方法来遍历这些立方体呢?因为这看起来就像是用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)])

2 个回答

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

当然可以!请把你想要翻译的内容发给我,我会帮你用简单易懂的语言解释清楚。

19

看看这个 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(...)

撰写回答