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 d
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'])
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()
}
print(diff_dicts({'a': 1, 'b': 1}, {'b': 2, 'c': 2}))
# {'c': (<class 'KeyError'>, 2), 'a': (1, <class 'KeyError'>), 'b': (1, 2)}
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.
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.
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.
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:
print set_1 - set_2
>>> {('FOO', 'BAR')}
Want a dictionary back? Easy, just:
dict(set_1 - set_2)
>>> {'FOO': 'BAR'}