python多维布尔数组?
它最多包含1000 x 1000 x 1000个元素,这对于python字典来说太大了 使用dict,大约30 x 1000 x 1000个元素,在我的机器上,它已经消耗了2gb的内存,所有东西都乱七八糟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整数数组,使用您自己的代码将多个
是否有任何模块可以处理其值仅为真/假的三维数组?我检查了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
当然,如果你想要更多的功能(比如切片),你必须多写一点
锯齿状数组将使用更多的内存(毕竟,您有1Mbitarray
对象和1Klist
对象的开销),并且可能会稍微慢一点,但这通常不会有太大区别
重要的决定因素应该是数据中的锯齿行是否固有错误。如果是,使用第二种溶液;如果有锯齿状或可调整大小的行可能有用,请使用前者。(请记住,如果可能的话,我会在任何一种解决方案上使用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,因此看起来您是对的。但看起来您可以使用它将其中一个维度打包为位。您可能需要解包切片等才能实际使用数据;我以前从未用过这个。但是,这可能仍然比在任何地方编写自己的打包/解包代码都要容易。