2

它最多包含 1000 x 1000 x 1000 个元素,这对于 python 字典来说太大了。

使用 dict,大约 30 x 1000 x 1000 个元素,在我的机器上它已经消耗了 2gb 的内存并且一切都被扔了。

任何可以处理其值仅为 True/False 的 3 维数组的模块?我检查了 bitarray http://pypi.python.org/pypi/bitarray,它看起来很合理并且用 C 编码,但是它看起来更像是一个比特流而不是一个数组,因为它只支持一维。

4

4 回答 4

6

numpy 是你的朋友:

import numpy as np
a = np.zeros((1000,1000,1000), dtype=bool)
a[1,10,100] = True

尽可能少地占用内存。

编辑:

如果您确实需要,您还可以查看集合模块中的 defaultdict 类容器,它不存储默认值的值。但如果不是必须的,请使用 numpy.

于 2012-11-28T21:13:03.590 回答
2

一个位数组列表的列表怎么样,也许用一个不错的 API 封装到你自己的类中?

或者,一个 3D NumPy 整数数组,使用您自己的代码将多个布尔值打包/解包到每个整数中。

于 2012-11-28T21:12:08.243 回答
1

numpyEnricoGiampieri 已经建议过,如果你可以使用它,你应该这样做。

否则,有两种选择:

正如 NPE 所建议的,锯齿状数组将是lists 中的list一个。bitarray这允许你有锯齿状的边界——例如,每一行可以是不同的宽度,甚至可以独立调整大小:

bits3d = [[bitarray.bitarray(1000) for y in range(1000)] for x in range(1000)]
myvalue = bits3d[x][y][z]

或者,正如 Xymotech 所建议的那样,对一维数组进行自己的索引:

bits3d = bitarray.bitarray(1000*1000*1000)
myvalue = bits3d[x + y*1000 + z*1000*1000]

无论哪种方式,您可能都希望将其包装在一个类中,因此您可以这样做:

bits3d = BitArray(1000, 1000, 1000)
myvalue = bits3d[x, y, z]

这很简单:

class Jagged3DBitArray(object):
    def __init__(self, xsize, ysize, zsize):
        self.lll = [[bitarray(zsize) for y in range(ysize)] 
                    for x in range(xsize)]
    def __getitem__(self, key):
        x, y, z = key
        return self.lll[x][y][z]
    def __setitem__(self, key, value):
        x, y, z = key
        self.lll[x][y][z] = value

class Fixed3DBitArray(object):
    def __init__(self, xsize, ysize, zsize):
        self.xsize, self.ysize, self.zsize = xsize, ysize, zsize
        self.b = bitarray(xsize * ysize * zsize)
    def __getitem__(self, key):
        x, y, z = key
        return self.b[x + y * self.ysize + z * self.ysize * self.zsize]
    def __setitem__(self, key, value):
        x, y, z = key
        self.b[x + y * self.ysize + z * self.ysize * self.zsize] = value

当然如果你想要更多的功能(比如切片),你必须多写一点。

锯齿状数组将使用更多内存(毕竟,您有 1Mbitarray对象和 1Klist对象的开销),并且可能会慢一些,但这通常不会有太大区别。

重要的决定因素应该是您的数据是否具有锯齿状行本身就是一个错误。如果是这样,请使用第二种解决方案;如果有锯齿状或可调整大小的行可能有用,请使用前者。(请记住numpy,如果可能的话,我会使用任何一种解决方案。)

于 2012-11-28T22:01:38.003 回答
0

从 unix 文件权限中获得灵感怎么样?755是为所有者读取、写入、执行和为其他所有人读取、执行。这是因为7转换为 binary 111

因此,您的 1000x1000x1000 bool 数组可能是 1000x1000 的ints 列表,其中每个 int 的二进制表示为您提供了一个表示 bool 数组的 1000“位”字符串。

所有这些都应该适合 1GB 的内存

于 2012-11-28T21:16:48.063 回答