我正在使用一个大矩阵(250x250x30 = 1,875,000 个单元格),并且我想要一种方法来为该矩阵中的每个单元格设置任意数量的标志,以某种易于使用且合理节省空间的方式。

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

我的问题是:我是否缺少另一种明显的方式来构建此类数据?

感谢大家的建议。我最终将一些建议汇总为一个,遗憾的是我只能选择一个答案,并且不得不忍受其他答案:

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

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
有帮助吗?

解决方案

我通常会使用 麻木 数组(大概是短整数,每个 2 个字节,因为您可能需要超过 256 个不同的值)——对于 <200 万个单元来说,这将占用不到 4MB 的空间。

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

一般来说,只要你有大的同质、稠密向量或数字矩阵,就考虑 numpy(或数组)——Python 内置列表在这个用例中非常浪费空间(因为你没有使用它们的通用性,并且这里不需要!-),节省内存也间接转化为节省时间(更好的缓存、更少的间接级别等)。

其他提示

如果每个单个细胞都将有一个标志你的溶液是好的。但是,如果你是一个稀疏的数据集,其中只有你的细胞的一小款将有标志的工作,你真正想要的是一本字典。你会想建立dictonary所以关键是该小区的位置的元组和值是标志的名单就像你在你的解决方案有。

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

下面我们有1,1,1细胞具有标志1,2和3和小区250,250,30具有标志4,5和6

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

可以定义一些常量具有两个值的不同,功率为:

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

和使用它们与布尔逻辑标志存储在只有一个整数,体育专业:

flags = FLAG1 | FLAG8

要检查是否启用了一个标志,你可以使用&操作:

flag1_enabled = flags & FLAG1

如果被使能标志,此表达式将返回一个非零值,这将在任何布尔操作来评价为真。如果该标志被禁用,则表达式将返回0,即评价为布尔运算假。

考虑使用享元模式共享电池特性:

http://en.wikipedia.org/wiki/Flyweight_pattern

位集合是你想要的,因为它允许你存储许多标志在使用一次只有一个固定大小整型(INT型)

以Robbie的建议一步...

flags = set()
x, y, flag = 34, 201, 3
flags.add((x, y, flag)) # set flag 3 at position (34, 201)
if (3, 2, 1) in flags: # check if flag 1 is at position (3, 2)
    # do something
else:
    # do something else

您还可以创建一个辅助类。

class Flags(object):
    def __init__(self):
        self.data = set()
    def add(self, x, y, flag):
        self.data.add((x, y, flag))
    def remove(self, x, y, flag):
        self.data.remove((x, y, flag))
    def contains(self, x, y, flag):
        return (x, y, flag) in self.data

您也可以实现Python的特殊方法,如__contains__,使其更易于使用。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top