我需要比较2个大型词典(超过60万个键)。
dict_old = {
1: {'value_1' : 'foo', 'value_2' : 'bar', ...},
2: {'value_1' : 'abc', 'value_2' : 'def', ...},
3: {....},
}
dict_new = {
1: {'value_1' : 'abc', 'value_2' : 'def', ...},
2: {'value_1' : '222', 'value_2' : '333', ...},
3: {'value_1' : 'foo', 'value_2' : 'bar', ...},
4: {'value_1' : 'abc', 'value_2' : 'def', ...},
...
}
我必须创建一个仅包含更改的新词典。
dict_update = {
1: {'value_1' : 'abc', 'value_2' : 'def', ...},
2: {'value_1' : '222', 'value_2' : '333', ...},
...
}
键是滚动数字,在新旧字典中不同。因此,我使用2 for循环来完成这项工作。 该过程需要60分钟才能运行。
dict_update = {}
for key_new in dict_new.keys():
for key_old in dict_old.keys():
if dict_new[key_new] == dict_old[key_old]:
add = False
break
else:
add = True
if add:
dict_update[key_new] = dict_new[key_new]
是否有更快/更Python化的方式来做到这一点?
答案 0 :(得分:1)
我将在这里进行一个疯狂的猜测:您想要的是dict_new
中的所有键值对,而dict_old
中没有相等的值。
代码的问题在于,对于dict2
中的每个键值对,您都在整个dict1
中进行线性搜索。因此,这花费了O(N*M)
时间(其中N=len(dict2)
和M=len(dict1)
),这很慢。
但是,如果您可以将dict1
中的值放在一组中,则不需要线性搜索;您可以进行恒定时间in
测试。您一开始就可以构建该集合。所以现在只有O(N+M)
,更好。
唯一的问题是您的值是字典,您不能将字典存储在集合中,因为它们是可变的。
有几种方法可以解决此问题,但最简单的方法是将dict转换为可哈希的对象,并保持相等性。例如,排序后的键/值对的元组是可哈希的(假设内部值是可哈希的,并且键是可排序的,这两个都是正确的),并且只要原始字典相等就将相等。
所以:
dict_old = {
1: {'value_1' : 'foo', 'value_2' : 'bar'},
2: {'value_1' : 'abc', 'value_2' : 'def'},
}
dict_new = {
1: {'value_1' : 'abc', 'value_2' : 'def'},
2: {'value_1' : '222', 'value_2' : '333'},
3: {'value_1' : 'foo', 'value_2' : 'bar'},
4: {'value_1' : 'abc', 'value_2' : 'def'},
}
def transform(d):
return tuple(sorted(d.items()))
set_old = set(transform(d) for d in dict_old.values())
dict_update = {key: value for key, value in dict_new.items()
if transform(value) not in set_old}
请注意,这并不能为您提供所需的输出,而只是为您提供:
{2: {'value_1': '222', 'value_2': '333'}}
但是您现有的代码可以给您完全一样的东西,而且这似乎是您要的东西。
答案 1 :(得分:0)
如何?
dict_old = {
1: {'value_1' : 'foo', 'value_2' : 'bar'},
2: {'value_1' : 'abc', 'value_2' : 'def'}
}
dict_new = {
1: {'value_1' : 'abc', 'value_2' : 'def'},
2: {'value_1' : '222', 'value_2' : '333'},
3: {'value_1' : 'foo', 'value_2' : 'bar'},
4: {'value_1' : 'abc', 'value_2' : 'def'},
}
old_hashes = set((k, frozenset(v.items())) for k, v in dict_old.items())
dictionary_update = {k: v for k, v in dict_new.items()
if (k, frozenset(v.items())) not in old_hashes}
这里的理由(如果您要的是)是每当滚动数字+键及其值不在dict_old
中时,它就会被添加到dict_update
中。 / p>
如果该代码不能完全满足您的需要(例如,也可以按照相反的方向进行操作,然后将其添加到dict_update
中),您应该可以对其进行调整。