0

我想使用搁置存储一个大字典。更具体地说,我所拥有的是一本字典,比如一个矩阵:

dict[key1][key2] = value

键的数量约为 5.000,这使得 5.000x5.000 个元素的矩阵无法存储在我的 4Gb 内存中。出于这个原因,我认为搁置可能是一个很好的解决方案。

尽管如此,我还没有找到任何关于如何有效地构建字典的文档。

到目前为止,我所做的是使用 shelve 创建一个包含常规字典的字典:

def create_entry(key1,key2,value,shelf): # shelf is the opened shelve file
   if key1 not in shelf: # first time we see this key, initialise it
    shelf[key1]={}
   # add the contents
   shelf[key1][key2]=value

这行得通,但似乎应该有更好的方法来充分利用搁置。有任何想法吗?

4

1 回答 1

3

您的解决方案唯一真正的问题是架子通过腌制它们来存储值,因此每次将第二级字典分页到磁盘时都必须对其进行腌制和取消腌制,这可能会产生巨大的性能成本。(当然,每个二级字典都必须适合内存,但这可能不是问题。)

如果这无关紧要,那么你所做的一切都很好。但如果是这样,还有其他两种选择。

您可以使用一些比搁置更复杂的数据库并围绕它构建自己的包装器。

或者,更简单:只需使用带有对作为键的单级字典:

def create_entry(key1, key2, value, shelf):
    shelf[(key1, key2)] = value

这样做的缺点是,如果您需要,例如,迭代子字典中的所有键或值,则key1必须迭代整个架子。它并不完全复杂((key2 for key1, key2 in shelf if key1 == key)),但它会慢很多。


上面的代码实际上并不能直接用于shelve,因为键必须是字符串。但是有很简单的方法可以结束它。就像shelvepickles 和 unpickles 值一样,您可以编写一个包装器而不是字符串化和解析键 - 例如:

def _mapkey(self, key):
    return ','.join(map(str, key))
def _unmapkey(self, key):
    return tuple(map(int, key.split(',')))
def __getitem__(self, key):
    return self.shelf[self._mapkey(key)]
def __iter__(self):
    return map(self._unmapkey, self.shelf)
# etc.

为了提高效率,最好分叉或子类化shelve,这样您就可bytes以为底层dbm密钥生成 a,而不是生成 astr以便shelve对其进行编码。然后你可以这样做:

def _mapkey(self, key):
    return struct.pack('>II', key)
def _unmapkey(self, key):
    return struct.unpack('<II', key)
于 2013-05-29T17:50:13.587 回答