python多维布尔数组?

python多维布尔数组?,python,arrays,boolean,Python,Arrays,Boolean,它最多包含1000 x 1000 x 1000个元素,这对于python字典来说太大了 使用dict,大约30 x 1000 x 1000个元素,在我的机器上,它已经消耗了2gb的内存,所有东西都乱七八糟 是否有任何模块可以处理其值仅为真/假的三维数组?我检查了bitarray,它似乎是合理的,并且是用C编写的,但是它更像是一个位流而不是数组,因为它只支持一维。一个bitarray列表怎么样,也许可以用一个漂亮的API包装到您自己的类中 或者,一个3D NumPy整数数组,使用您自己的代码将多个

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

使用dict,大约30 x 1000 x 1000个元素,在我的机器上,它已经消耗了2gb的内存,所有东西都乱七八糟


是否有任何模块可以处理其值仅为真/假的三维数组?我检查了bitarray,它似乎是合理的,并且是用C编写的,但是它更像是一个位流而不是数组,因为它只支持一维。

一个bitarray列表怎么样,也许可以用一个漂亮的API包装到您自己的类中

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

NumPy是您的朋友:

import numpy as np
a = np.zeros((1000,1000,1000), dtype=bool)
a[1,10,100] = True
具有尽可能少的内存占用空间

编辑:
如果确实需要,还可以查看collections模块中的defaultdict类容器,它不存储默认值的值。但如果它不是必须的,那么就使用numpy。

从unix文件权限中获得灵感如何<代码>755为所有者读、写、执行,为其他人读、执行。这是因为
7
转换为二进制
111

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


所有这些都应该放在1GB以下的内存中

numpy
已经由EnricoGiampieri建议过了,如果你能使用它,你应该这样做

否则,有两种选择:

NPE建议的锯齿状数组是
list
list
位数组的
s。这允许您具有锯齿状边界,例如,每行可以具有不同的宽度,甚至可以独立调整大小:

bits3d = [[bitarray.bitarray(1000) for y in range(1000)] for x in range(1000)]
myvalue = bits3d[x][y][z]
或者,按照Xymostech的建议,在1-D数组上创建自己的索引:

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
当然,如果你想要更多的功能(比如切片),你必须多写一点

锯齿状数组将使用更多的内存(毕竟,您有1M
bitarray
对象和1K
list
对象的开销),并且可能会稍微慢一点,但这通常不会有太大区别


重要的决定因素应该是数据中的锯齿行是否固有错误。如果是,使用第二种溶液;如果有锯齿状或可调整大小的行可能有用,请使用前者。(请记住,如果可能的话,我会在任何一种解决方案上使用
numpy

你可以制作一个
bitarray
,然后自己做索引。在许多编程环境中,人们使用“array”是指“正好有一个维度的数组”,而不是一般意义上的数组。这就是为什么你经常发现人们在做数组数组(一个
list的
list的
s的
s的
bit数组的
s)或者在一维数组中伪造一个N-D数组(
a[z*1000*1000+y*1000+y*1000+x]
而不是
a[x,y,z]
),因为他们实际上没有通用的数组类型,只有一维数组类型。我被你的编辑弄糊涂了。“不存储给定值的值”是什么意思?我认为您可能不理解默认dict实际上是什么或是做什么的。我认为编辑意味着您可以将默认值设置为true或false,然后只需要存储另一个位置。基本上是一个稀疏数组。正如@tcaswell所说,我指的是默认dict的默认值集。这肯定不是我最好的英语时刻。恕我直言,我认为内存占用越少越好。好吧,这需要每个布尔值一个字节。我认为
list的
list的
s的
bit数组的
s比
list的
list的
int的
s的+1更简单、更清晰。但是当你可以使用一个整数的numpy数组时,你不需要手动将数据打包到一个整数的numpy数组中。@abarnert:你确定吗?我认为NumPy会使用一个字节,而不是一位。你是说事实并非如此?我还没有测试。我想我从来没有使用过
numpy
来表示
bool
值……但是IIRC,很久以前,使用
numeric
时,您必须对1位bool数组和8位bool数组使用不同的类型,所以您可能是对的。(无论如何,即使是1字节的值也会降到略高于1GB而不是6GB…)而不是猜测:
numpy.zero(1000,1000,1000,dtype=bool)。dtype
返回
100000000
,1GB,因此看起来您是对的。但看起来您可以使用它将其中一个维度打包为位。您可能需要解包切片等才能实际使用数据;我以前从未用过这个。但是,这可能仍然比在任何地方编写自己的打包/解包代码都要容易。