我搜索并发现了一些像datadiff,dictdiff-master这样的插件/软件包,但是当我在Python 2.7中尝试它时,它说没有定义这样的模块。
我在这里使用了set。
first_dict = {}
second_dict = {}
value = set(second_dict)-set(first_dict)
print value
输出>>>设置([' SCD-3547',' SCD-3456'])
我只得到钥匙,我甚至需要获得价值。
答案 0 :(得分:45)
我认为最好使用集合的对称差分操作(https://docs.python.org/2/library/sets.html)。
>>> dict1 = {1:'donkey', 2:'chicken', 3:'dog'}
>>> dict2 = {1:'donkey', 2:'chimpansee', 4:'chicken'}
>>> set1 = set(dict1.items())
>>> set2 = set(dict2.items())
>>> set1 ^ set2
{(2, 'chimpansee'), (4, 'chicken'), (2, 'chicken'), (3, 'dog')}
它是对称的,因为:
>>> set2 ^ set1
{(2, 'chimpansee'), (4, 'chicken'), (2, 'chicken'), (3, 'dog')}
使用差异运算符时不是这种情况
>>> set1 - set2
{(2, 'chicken'), (3, 'dog')}
>>> set2 - set1
{(2, 'chimpansee'), (4, 'chicken')}
但是,将结果集转换为字典可能不是一个好主意,因为您可能会丢失信息:
>>> dict(set1 ^ set2)
{2: 'chicken', 3: 'dog', 4: 'chicken'}
答案 1 :(得分:38)
使用字典理解尝试以下代码段:
value = { k : second_dict[k] for k in set(second_dict) - set(first_dict) }
在上面的代码中,我们找到了的密钥,然后使用相应的值重建dict
。
答案 2 :(得分:6)
另一种解决方案是dictdiffer
(https://github.com/inveniosoftware/dictdiffer)。
import dictdiffer
a_dict = {
'a': 'foo',
'b': 'bar',
'd': 'barfoo'
}
b_dict = {
'a': 'foo',
'b': 'BAR',
'c': 'foobar'
}
for diff in list(dictdiffer.diff(a_dict, b_dict)):
print diff
diff是一个元组,其中包含更改类型,更改的值以及条目的路径。
('change', 'b', ('bar', 'BAR'))
('add', '', [('c', 'foobar')])
('remove', '', [('d', 'barfoo')])
答案 3 :(得分:5)
你是正确的看待使用一套,我们只需要深入挖掘,让你的方法工作。
首先,示例代码:
test_1 = {"foo": "bar", "FOO": "BAR"}
test_2 = {"foo": "bar", "f00": "b@r"}
我们现在可以看到两个词典都包含类似的键/值对:
{"foo": "bar", ...}
每个字典还包含完全不同的键值对。但是我们如何发现差异呢?字典不支持这一点。相反,你想要使用一套。
以下是如何将每个字典转换为我们可以使用的集合:
set_1 = set(test_1.items())
set_2 = set(test_2.items())
这将返回包含一系列元组的集合。每个元组代表字典中的一个键/值对。
现在,找出set_1和set_2之间的区别:
print set_1 - set_2
>>> {('FOO', 'BAR')}
想要一本字典吗?简单,只是:
dict(set_1 - set_2)
>>> {'FOO': 'BAR'}
答案 4 :(得分:3)
此函数仅根据字典键为您提供所有差异(以及保持不变的差异)。它还突出了一些不错的Dict理解,Set操作和python 3.6类型注释:)
def get_dict_diffs(a: Dict[str, Any], b: Dict[str, Any]) -> Tuple[Dict[str, Any], Dict[str, Any], Dict[str, Any], Dict[str, Any]]:
added_to_b_dict: Dict[str, Any] = {k: b[k] for k in set(b) - set(a)}
removed_from_a_dict: Dict[str, Any] = {k: a[k] for k in set(a) - set(b)}
common_dict_a: Dict[str, Any] = {k: a[k] for k in set(a) & set(b)}
common_dict_b: Dict[str, Any] = {k: b[k] for k in set(a) & set(b)}
return added_to_b_dict, removed_from_a_dict, common_dict_a, common_dict_b
如果您想比较词典值:
values_in_b_not_a_dict = {k : b[k] for k, _ in set(b.items()) - set(a.items())}
答案 5 :(得分:0)
这个怎么样?不是很漂亮而是明确。
orig_dict = {'a' : 1, 'b' : 2}
new_dict = {'a' : 2, 'v' : 'hello', 'b' : 2}
updates = {}
for k2, v2 in new_dict.items():
if k2 in orig_dict:
if v2 != orig_dict[k2]:
updates.update({k2 : v2})
else:
updates.update({k2 : v2})
#test it
#value of 'a' was changed
#'v' is a completely new entry
assert all(k in updates for k in ['a', 'v'])
答案 6 :(得分:0)
def flatten_it(d):
if isinstance(d, list) or isinstance(d, tuple):
return tuple([flatten_it(item) for item in d])
elif isinstance(d, dict):
return tuple([(flatten_it(k), flatten_it(v)) for k, v in sorted(d.items())])
else:
return d
dict1 = {'a': 1, 'b': 2, 'c': 3}
dict2 = {'a': 1, 'b': 1}
print set(flatten_it(dict1)) - set(flatten_it(dict2)) # set([('b', 2), ('c', 3)])
# or
print set(flatten_it(dict2)) - set(flatten_it(dict1)) # set([('b', 1)])
答案 7 :(得分:0)
使用对称差集运算符的函数,如其他答案所述,该函数保留值的原点:
def diff_dicts(a, b, missing=KeyError):
"""
Find keys and values which differ from `a` to `b` as a dict.
If a value differs from `a` to `b` then the value in the returned dict will
be: `(a_value, b_value)`. If either is missing then the token from
`missing` will be used instead.
:param a: The from dict
:param b: The to dict
:param missing: A token used to indicate the dict did not include this key
:return: A dict of keys to tuples with the matching value from a and b
"""
return {
key: (a.get(key, missing), b.get(key, missing))
for key in dict(
set(a.items()) ^ set(b.items())
).keys()
}
print(diff_dicts({'a': 1, 'b': 1}, {'b': 2, 'c': 2}))
# {'c': (<class 'KeyError'>, 2), 'a': (1, <class 'KeyError'>), 'b': (1, 2)}
我们对取物品产生的元组使用对称差集运算符。这会根据这两个字典生成一组不同的(key, value)
元组。
然后我们据此做出新的决定,将密钥折叠在一起并对其进行迭代。这些是从一个字典更改为下一个字典的唯一键。
然后,当这些键不存在时,我们将使用这些键以及来自每个dict的值的元组代替丢失的令牌来组成一个新的dict。
答案 8 :(得分:0)
不确定这是 OP 要求的内容,但是当我遇到这个问题时,这就是我正在寻找的内容 - 具体来说,如何逐键显示两个字典之间的差异:
陷阱:当一个字典缺少键,而第二个字典有一个 None 值时,函数会假设它们是相似的
这根本没有优化 - 适用于小字典
def diff_dicts(a, b, drop_similar=True):
res = a.copy()
for k in res:
if k not in b:
res[k] = (res[k], None)
for k in b:
if k in res:
res[k] = (res[k], b[k])
else:
res[k] = (None, b[k])
if drop_similar:
res = {k:v for k,v in res.items() if v[0] != v[1]}
return res
print(diff_dicts({'a': 1}, {}))
print(diff_dicts({'a': 1}, {'a': 2}))
print(diff_dicts({'a': 2}, {'a': 2}))
print(diff_dicts({'a': 2}, {'b': 2}))
print(diff_dicts({'a': 2}, {'a': 2, 'b': 1}))
输出:
{'a': (1, None)}
{'a': (1, 2)}
{}
{'a': (2, None), 'b': (None, 2)}
{'b': (None, 1)}
答案 9 :(得分:0)
一个解决方案是使用 unittest
模块:
from unittest import TestCase
TestCase().assertDictEqual(expected_dict, actual_dict)
从How can you test that two dictionaries are equal with pytest in python获得
答案 10 :(得分:-1)
老问题,但以为我还是会分享我的解决方案。很简单。
dicta_set = set(dicta.items()) # creates a set of tuples (k/v pairs)
dictb_set = set(dictb.items())
setdiff = dictb_set.difference(dicta_set) # any set method you want for comparisons
for k, v in setdiff: # unpack the tuples for processing
print(f"k/v differences = {k}: {v}")
此代码创建代表k / v对的两组元组。然后,它使用您选择的set方法来比较元组。最后,它解压缩了元组(k / v对)以进行处理。
答案 11 :(得分:-1)
这将返回一个新的字典(仅更改数据)。
def get_difference(obj_1: dict, obj_2: dict) -> dict:
result = {}
for key in obj_1.keys():
value = obj_1[key]
if isinstance(value, dict):
difference = get_difference(value, obj_2.get(key, {}))
if difference:
result[key] = difference
elif value != obj_2.get(key):
result[key] = obj_2.get(key, None)
return result