我正在做一些索引,内存已足够,但CPU却没有。所以我有一个庞大的字典,然后是一个较小的字典,我正在与较大的字典合并:
big_dict = {"the" : {"1" : 1, "2" : 1, "3" : 1, "4" : 1, "5" : 1}}
smaller_dict = {"the" : {"6" : 1, "7" : 1}}
#after merging
resulting_dict = {"the" : {"1" : 1, "2" : 1, "3" : 1, "4" : 1, "5" : 1, "6" : 1, "7" : 1}}
我的问题是两个词中的值,我应该使用dict(如上所示)还是列表(如下所示),当我的优先级是尽可能多地使用内存以充分利用我的CPU时?
为了澄清,使用列表看起来像:
big_dict = {"the" : [1, 2, 3, 4, 5]}
smaller_dict = {"the" : [6,7]}
#after merging
resulting_dict = {"the" : [1, 2, 3, 4, 5, 6, 7]}
旁注:我使用嵌套到dict中的dict而不是嵌套在dict中的set的原因是因为JSON不会让我做json.dumps,因为set不是键/值对,它是(就JSON库而言){“a”,“series”,“of”,“keys”}
此外,在选择使用dict到列表之后,我将如何在CPU方面实现最有效的合并方法?
我很感激帮助。
答案 0 :(得分:2)
嗯。我会首先采用dict-of-dicts方法,因为Python有一个最精细调整的dict实现,所以我非常怀疑你使用dict-of-lists可以做得更好。
至于合并词汇,这应该足够了:
for key, value in smaller_dict.iteritems():
try:
big_dict[key].update(value)
except KeyError:
big_dict[key] = dict(value)
我可能还会尝试使用子类json.JSONEncoder
来序列化集类型:
class SetEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, set):
return dict.fromkeys(obj)
return json.JSONEncoder.default(self, obj)
然而,后一种方法可能会在序列化方面增加一些开销,并且您还需要在反序列化时将这些dicts转换为set,或者通过子类化json.JSONDecoder
或者在额外的步骤中自己完成。
答案 1 :(得分:2)
这实际上取决于你想要对内部列表/词典中的值做什么。如果在添加新条目时,您希望内部列表只包含唯一值,那么对于大型列表,列表实现将多更慢。它大致缩放为O(n),而不是字典的O(1)[平均情况]。
如果你不关心那些内部列表中的倍数,那么这是一个更接近的事情。
我会像你一样使用词典。 Python的词典非常高效(作为试图在C中为实时应用程序实现字典数据结构的人)。
至于不使用套装。更好(因为内存不是问题,你说),调整序列化,并让代码的速度关键部分尽可能简单。反序列化后,只需将列表转换为集合:
big_dict = {"the" : [1, 2, 3, 4, 5]} # imagine we got this from JSON
for key, value in big_dict:
big_dict[key] = set(value)
应该这样做。除非您一直在对整个索引进行序列化/反序列化,否则这些增加的预处理成本应该在足够多的请求中摊销。
或者,您可以使用JSON注册编码器和解码器,以便自动执行此转换。但是,当问题很小并且包含在内时,我通常不会打扰。
因此,在基于字典的方法中,您可以这样做:
for key, value in smaller_dict.items():
if key in big_dict:
big_dict[key].update(value)
else:
big_dict[key] = value
如果您希望big_dict仅复制字典,请在最后一行使用dict(value)
代替value
。您也可以在最后一个循环中使用try:
和except KeyError
,但if
... else
的速度要快一些(在我的机器上,YMMV)。
答案 2 :(得分:1)
任何散列容器都会比这种东西更好。
我仍然使用set
代替dict
;如果您在使用json.dumps
时遇到问题,可以在序列化时将设置转换为字典来解决问题:dict.fromkeys(the_set, 1)
并将它们拉出来:set(the_dict.keys())
通过注册JSON提供程序比使用它更容易。
至于合并:merged_set = bigger_set.union(smaller_set)