Python中的标志

2024-06-28 18:44:02 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在处理一个大矩阵(250x250x30=1875000个单元格),我想用一种方法为这个矩阵中的每个单元格设置任意数量的标志,这种方法使用简单,而且节省空间。

我最初的计划是一个250x250x30列表数组,其中的每个元素都类似于:["FLAG1","FLAG8","FLAG12"]。然后我将它改为只存储整数:[1,8,12]。这些整数由getter/setter函数内部映射到原始标志字符串。这只使用250mb,每个点有8个标志,这在内存方面是很好的。

我的问题是:我是否遗漏了另一种构造此类数据的明显方法?

谢谢大家的建议。最后,我把一些建议整合成一个,可惜我只能选择一个答案,而不得不接受对其他答案的投票:

编辑:呃,我这里的初始代码(使用集合作为3d numpy数组的基本元素)使用了大量内存。这个新版本在填充randint(0,2**1000)时使用大约500mb。

import numpy

FLAG1=2**0
FLAG2=2**1
FLAG3=2**2
FLAG4=2**3

(x,y,z) = (250,250,30)

array = numpy.zeros((x,y,z), dtype=object)


def setFlag(location,flag):
    array[location] |= flag
def unsetFlag(location,flag):
    array[location] &= ~flag

Tags: 方法内存答案numpy元素标志def矩阵
3条回答

您可以用两个值的不同幂定义一些常数:

FLAG1 = 0x01
FLAG8 = 0x02
FLAG12 = 0x04
...

并将它们与布尔逻辑一起使用,以仅将标志存储在一个整数中,p.e.:

flags = FLAG1 | FLAG8

要检查是否启用了标志,可以使用&运算符:

flag1_enabled = flags & FLAG1

如果启用该标志,则此表达式将返回一个非零值,在任何布尔操作中该值都将被计算为True。如果该标志被禁用,表达式将返回0,在布尔操作中该值被计算为False。

如果每个单元都有一个标志,那么你的解决方案是好的。但是,如果您使用的是稀疏数据集,其中只有一小部分单元格具有标记,那么您真正需要的是字典。您需要设置dictional,以便键是单元格位置的元组,值是解决方案中的标志列表。

allFlags = {(1,1,1):[1,2,3], (250,250,30):[4,5,6]}

这里我们有1,1,1单元格有标志1,2和3,250250,30单元格有标志4,5和6

编辑-固定键元组,谢谢安德烈,和字典语法。

我通常使用一个numpy数组(可能是短整型,每个2字节,因为您可能需要超过256个不同的值),对于200万个单元格来说,这个数组的大小不到4MB。

如果出于某种原因,我负担不起numpy依赖性(例如在App Engine上,它不支持numpy),我会使用标准库array模块-它只支持一维数组,但对于大型同构数组,它与numpy一样节省空间,而且您提到的getter/setter例程可以很好地“线性化”一个3项元组,这是您的自然索引到一维数组的单个整数索引中。

一般来说,当您有大量的同质的、密集的向量或数字矩阵时,请考虑numpy(或数组)——在这个用例中,Python内置列表非常浪费空间(由于它们的通用性,您不需要也不需要在这里使用它们!)!-),而节省内存也间接地转化为节省时间(更好的缓存、更少的间接寻址级别等)。

相关问题 更多 >