我正在编写一个字典结构,其中我有一个文档字典,每个文档都有一个单词字典(其中每个键都是word_id(整数),值是计数),这样:
document_dict = { "doc1": {1:2, 2:10, 10:2, 100: 1}, "doc2": {10:2, 20:10, 30:2, 41: 19},...}
请注意,内部词典非常稀疏,所以即使我有250K字,我也不希望每个文档的密钥超过1K。
在每次迭代中,我需要总结一个单词的词典:计入其中一个文档,例如我需要将{1:2,2:10,10:2,120:1}的新词与“doc1”联合起来:{1:2,2:10,10:2,100:1}。
现在,我的实现运行速度非常快,但是2小时后内存不足(我使用的是40GB服务器)。
我总结钥匙的方式是这样的:
假设new_dict是新单词:我想要添加到doc1的计数对,例如:
new_dict = {1:2, 2:10, 10:2, 120: 1}
doc1 = {1:2, 2:10, 10:2, 100: 1}
for item in new_dict:
doc1[item] = doc1.get(item, 0) + new_dict[item]
然后因为用字典运行代码根本不可能,因为我的dicts在很短的时间内变得非常大,我试图将字典实现为2个列表的列表:例如doc1 = [[],[]]其中第一个列表保存键,第二个键保留值。
现在,当我想要像这样结合2个结构时,我首先尝试获取doc1中new_dict的每个项目的索引。如果我成功获得索引,则表示密钥已经在doc1中,因此我可以更新相应的值。否则,它还没有在doc1中,所以我将新键和值追加()到列表的末尾。然而,这种方法运行得非常慢(在dict版本中,我能够在2小时内处理多达600K文档,现在我只能在15小时内处理250K文档)。
所以我的问题是:如果我想使用字典结构(key,val)对,我需要联合2个dicts的键并在每次迭代中求和它们的值,有没有办法有效地实现这个更多的空间?
答案 0 :(得分:1)
它不一定更节省空间,但我建议使用shelve
模块切换到基于磁盘的字典,这样您就不必一次将整个字典放在内存中。
它们非常易于使用,因为它们支持熟悉的字典界面,如下所示:
import shelve
document_dict = shelve.open('document_dict', writeback=True)
document_dict.update({"doc1": {1:2, 2:10, 10:2, 100: 1},
"doc2": {10:2, 20:10, 30:2, 41: 19},
"doc3": {1:2, 2:10, 10:2, 100: 1},})
new_dict = {1:2, 2:10, 10:2, 120: 1}
doc = document_dict.get("doc3", {}) # get current value, if any
for item in new_dict:
doc[item] = doc.get(item, 0) + new_dict[item] # update version in memory
document_dict["doc3"] = doc # write modified (or new) entry to disk
document_dict.sync() # clear cache
print document_dict
document_dict.close()
输出:
{'doc2': {41: 19, 10: 2, 20: 10, 30: 2},
'doc3': {120: 1, 1: 4, 2: 20, 100: 1, 10: 4},
'doc1': {1: 2, 2: 10, 100: 1, 10: 2}}