我需要有效地拥有一个差异字典,该差异字典告诉我某个主字典与当前某个时刻之间的区别。
我需要有更改内容的完整路径,而不仅仅是更改的值。
例如:
primary_dict = {'a': 5, 'b':{'c': 9}, 'd':10}
和将会是
diff_dict = {'a':6, 'b':{'c':8}}
表示目前
primary_dict = {'a':6, 'b':{'c':8}, 'd':10}
当将值添加到字典时,我可以创建差异
我在线上看过,但是只发现两个字典之间的比较,效率不高,因为我需要比较的字典很大,保存了2次,然后递归比较所有,似乎对当前的问题大有帮助
编辑: 将问题更改为更重要。 就像我收到通知一样,反映我需要的问题是: 如何在不创建新变量的情况下随时间更改字典? 感谢@CristiFati和@Vishnudev的更正
答案 0 :(得分:0)
使用dictdiffer
库
>>> from dictdiffer import diff
>>> before_change = {'a': 5, 'b':{'c': 9}, 'd':10}
>>> after_change = {'a': 6, 'b':{'c':8, 'd': 10}, 'd':10}
>>> list(diff(before_change, after_change))
[('change', 'a', (5, 6)), ('change', 'b.c', (9, 8)), ('add', 'b', [('d', 10)])]
对于已删除的密钥,
>>> before_change = {'a': 5, 'b':{'c': 9}, 'd':10}
>>> after_change = {'a': 6, 'b':{'d': 10}, 'd':10}
>>> list(diff(before_change, after_change))
[('change', 'a', (5, 6)), ('add', 'b', [('d', 10)]), ('remove', 'b', [('c', 9)])]
答案 1 :(得分:0)
OOPS也许可以解决。
该词典只能由具有创建更改记录的公共功能进行编辑。
答案 2 :(得分:0)
复杂的解决方案(基于set
操作和递归函数),用于扩展的复杂输入字典:
正如标题所述,感兴趣的条件是“当插入值时” 。
# extended input samples
before_change = {'a': 5, 'b': {'c': 9}, 'd': 10, 'g': {'h': {'k': 100}}}
after_change = {'a': 6, 'b': {'c': 9, 'f': 1}, 'd': 10, 'g': {'h': {'k': 300}}, 'e': 11}
def dict_diff(before, after):
"""Compute difference between dictionaries.
Fetchs path to the innermost changed item"""
new_keys = set(before) ^ set(after)
diff = {k: after[k] for k in new_keys} # detecting new keys/items beforehand
for k in set(before) & set(after): # process intersected keys
if before[k] != after[k]:
if type(before[k]) is dict and type(after[k]) is dict:
inner_diff = dict_diff(before[k], after[k])
if inner_diff: diff[k] = inner_diff
else:
diff[k] = after[k]
return diff
print(dict_diff(before_change, after_change))
输出:
{'e': 11, 'b': {'f': 1}, 'g': {'h': {'k': 300}}, 'a': 6}
答案 3 :(得分:0)
已经存在类似的问题:[SO]: How to get the difference between two dictionaries in Python?。
您可以使用递归方法。
code.py :
#!/usr/bin/env python3
import sys
def dummy_dict_diff(initial, final):
ret = dict()
for final_key, final_val in final.items():
if final_key not in initial: # Handle new keys
ret[final_key] = final_val
continue
initial_val = initial[final_key]
if final_val != initial_val:
if type(final_val) != type(initial_val):
ret[final_key] = final_val
elif isinstance(final_val, (dict,)):
ret[final_key] = dummy_dict_diff(initial_val, final_val)
elif isinstance(final_val, (list, tuple)):
ret[final_key] = final_val # This would also require sequence diffs
else:
ret[final_key] = final_val
deleted_keys = [item for item in initial if item not in final] # Deleted keys
for deleted_key in deleted_keys:
ret[deleted_key] = initial[deleted_key]
return ret
def main():
before = {
"a": 5,
"b": {
"c": 9
},
"d": 10
}
after = {
"a": 6,
"b": {
"c": 8
},
"d": 10
}
print("Difference: {:}".format(dummy_dict_diff(before, after)))
if __name__ == "__main__":
print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
main()
print("\nDone.")
注释:
输出:
[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q056617962]> "e:\Work\Dev\VEnvs\py_064_03.07.03_test0\Scripts\python.exe" code.py Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)] on win32 Difference: {'a': 6, 'b': {'c': 8}} Done.
答案 4 :(得分:0)
您可以使用理解词典:
actual_dict = {'a': 5, 'b':{'c': 9}, 'd':10}
diff_dict = {'a':6, 'b':{'c':8}}
primary_dict = {x: actual_dict[x] if x not in diff_dict.keys() else diff_dict[x] for x in actual_dict.keys()}
print(primary_dict)
输出:
{'a':6,'b':{'c':8},'d':10}
答案 5 :(得分:0)
您可以使用以下python代码获取两个字典之间的区别:
before_change = {'a': 5, 'b':{'c': 9}, 'd':10}
after_change = {'a': 6, 'b':{'c':8}, 'd':10}
bc_values = list(before_change.values())
ac_values = list(after_change.values())
ac_keys = list(after_change.keys())
for item in range(len(bc_values)):
if ac_values[item] == bc_values[item] :
after_change.pop(ac_keys[item])
print(after_change)
此代码的输出是:
{'a': 6, 'b': {'c': 8}}