如何获得Python中两个字典之间的差异?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32815640/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 12:20:03  来源:igfitidea点击:

How to get the difference between two dictionaries in Python?

python

提问by Jayashree Shetty

I have two dictionaries. I need to find the difference between the two which should give me both key and value.

我有两本字典。我需要找到两者之间的区别,这应该给我带来关键和价值。

I have searched and found some addons/packages like datadiff, dictdiff-master but when I try it in Python 2.7 it says no such module defined.

我搜索并找到了一些插件/包,如 datadiff、dictdiff-master,但是当我在 Python 2.7 中尝试它时,它说没有定义这样的模块。

I used set here.

我在这里使用了 set 。

first_dict = {}
second_dict = {}

value = set(second_dict)-set(first_dict)
print value

output >>>set(['SCD-3547', 'SCD-3456'])

输出>>>设置(['SCD-3547','SCD-3456'])

I am getting only key, I need to even get the values.

我只得到钥匙,我什至需要得到价值。

采纳答案by óscar López

Try the following snippet, using a dictionary comprehension:

使用字典理解尝试以下代码片段:

value = { k : second_dict[k] for k in set(second_dict) - set(first_dict) }

In the above code we find the difference of the keysand then rebuild a dicttaking the corresponding values.

在上面的代码中,我们找到的差异然后dict使用相应的值重建一个。

回答by jesseops

You were right to look at using a set, we just need to dig in a little deeper to get your method to work.

您认为使用集合是正确的,我们只需要更深入地挖掘即可让您的方法发挥作用。

First, the example code:

首先,示例代码:

test_1 = {"foo": "bar", "FOO": "BAR"}
test_2 = {"foo": "bar", "f00": "b@r"}

We can see right now that both dictionaries contain a similar key/value pair:

我们现在可以看到两个字典都包含一个相似的键/值对:

{"foo": "bar", ...}

Each dictionary also contains a completely different key value pair. But how do we detect the difference? Dictionaries don't support that. Instead, you'll want to use a set.

每个字典还包含一个完全不同的键值对。但是我们如何检测差异呢?字典不支持。相反,您需要使用集合。

Here is how to turn each dictionary into a set we can use:

以下是如何将每个字典变成我们可以使用的集合:

set_1 = set(test_1.items())
set_2 = set(test_2.items())

This returns a set containing a series of tuples. Each tuple represents one key/value pair from your dictionary.

这将返回一个包含一系列元组的集合。每个元组代表您字典中的一个键/值对。

Now, to find the difference between set_1 and set_2:

现在,要找出 set_1 和 set_2 之间的区别:

print set_1 - set_2
>>> {('FOO', 'BAR')}

Want a dictionary back? Easy, just:

想拿回字典吗?很简单,只是:

dict(set_1 - set_2)
>>> {'FOO': 'BAR'}

回答by Roedy

I think it's better to use the symmetric difference operation of sets to do that Here is the link to the doc.

我认为最好使用集合的对称差分运算来做到这一点这里是 doc 的链接

>>> 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')}

It is symmetric because:

它是对称的,因为:

>>> set2 ^ set1
{(2, 'chimpansee'), (4, 'chicken'), (2, 'chicken'), (3, 'dog')}

This is not the case when using the difference operator.

使用差分运算符时情况并非如此。

>>> set1 - set2
{(2, 'chicken'), (3, 'dog')}
>>> set2 - set1
{(2, 'chimpansee'), (4, 'chicken')}

However it may not be a good idea to convert the resulting set to a dictionary because you may lose information:

但是,将结果集转换为字典可能不是一个好主意,因为您可能会丢失信息:

>>> dict(set1 ^ set2)
{2: 'chicken', 3: 'dog', 4: 'chicken'}

回答by Christian Berendt

Another solution would be dictdiffer(https://github.com/inveniosoftware/dictdiffer).

另一种解决方案是dictdifferhttps://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

A diff is a tuple with the type of change, the changed value, and the path to the entry.

diff 是一个包含更改类型、更改值和条目路径的元组。

('change', 'b', ('bar', 'BAR'))
('add', '', [('c', 'foobar')])
('remove', '', [('d', 'barfoo')])

回答by henryHyman

This function gives you all the diffs (and what stayed the same) based on the dictionary keys only. It also highlights some nice Dict comprehension, Set operations and python 3.6 type annotations :)

此函数仅根据字典键为您提供所有差异(以及保持不变的差异)。它还强调了一些不错的 Dict 理解、集合操作和 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

If you want to compare the dictionary values:

如果要比较字典

values_in_b_not_a_dict = {k : b[k] for k, _ in set(b.items()) - set(a.items())}

回答by joshE

What about this? Not as pretty but explicit.

那这个呢?不那么漂亮,但很明确。

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'])

回答by cadl

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)])

回答by Jon Betts

A function using the symmetric difference set operator, as mentioned in other answers, which preserves the origins of the values:

使用对称差分集运算符的函数,如其他答案中所述,它保留了值的原点:

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()
    }

Example

例子

print(diff_dicts({'a': 1, 'b': 1}, {'b': 2, 'c': 2}))

# {'c': (<class 'KeyError'>, 2), 'a': (1, <class 'KeyError'>), 'b': (1, 2)}

How this works

这是如何工作的

We use the symmetric difference set operator on the tuples generated from taking items. This generates a set of distinct (key, value)tuples from the two dicts.

我们在取项生成的元组上使用对称差分集运算符。这会(key, value)从两个字典中生成一组不同的元组。

We then make a new dict from that to collapse the keys together and iterate over these. These are the only keys that have changed from one dict to the next.

然后我们从中创建一个新的 dict 来将键折叠在一起并迭代这些键。这些是从一个字典更改为下一个字典的唯一键。

We then compose a new dict using these keys with a tuple of the values from each dict substituting in our missing token when the key isn't present.

然后我们使用这些键组成一个新的字典,当键不存在时,每个字典中的值的元组替换我们丢失的标记。

回答by zs4

Old question, but thought I'd share my solution anyway. Pretty simple.

老问题,但我想无论如何我都会分享我的解决方案。很简单。

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}")

This code creates two sets of tuples representing the k/v pairs. It then uses a set method of your choosing to compare the tuples. Lastly, it unpacks the tuples (k/v pairs) for processing.

此代码创建两组表示 k/v 对的元组。然后它使用您选择的 set 方法来比较元组。最后,它解包元组(k/v 对)进行处理。