# Comparing two dictionaries and checking how many (key, value) pairs are equal

Posted on

### Question :

Comparing two dictionaries and checking how many (key, value) pairs are equal

I have two dictionaries, but for simplification, I will take these two:

``````>>> x = dict(a=1, b=2)
>>> y = dict(a=2, b=2)
``````

Now, I want to compare whether each `key, value` pair in `x` has the same corresponding value in `y`. So I wrote this:

``````>>> for x_values, y_values in zip(x.iteritems(), y.iteritems()):
if x_values == y_values:
print 'Ok', x_values, y_values
else:
print 'Not', x_values, y_values
``````

And it works since a `tuple` is returned and then compared for equality.

My questions:

Is this correct? Is there a better way to do this? Better not in speed, I am talking about code elegance.

UPDATE: I forgot to mention that I have to check how many `key, value` pairs are equal.

If you want to know how many values match in both the dictionaries, you should have said that ðŸ™‚

Maybe something like this:

``````shared_items = {k: x[k] for k in x if k in y and x[k] == y[k]}
print len(shared_items)
``````

What you want to do is simply `x==y`

What you do is not a good idea, because the items in a dictionary are not supposed to have any order. You might be comparing `[('a',1),('b',1)]` with `[('b',1), ('a',1)]` (same dictionaries, different order).

For example, see this:

``````>>> x = dict(a=2, b=2,c=3, d=4)
>>> x
{'a': 2, 'c': 3, 'b': 2, 'd': 4}
>>> y = dict(b=2,c=3, d=4)
>>> y
{'c': 3, 'b': 2, 'd': 4}
>>> zip(x.iteritems(), y.iteritems())
[(('a', 2), ('c', 3)), (('c', 3), ('b', 2)), (('b', 2), ('d', 4))]
``````

The difference is only one item, but your algorithm will see that all items are different

``````def dict_compare(d1, d2):
d1_keys = set(d1.keys())
d2_keys = set(d2.keys())
shared_keys = d1_keys.intersection(d2_keys)
removed = d2_keys - d1_keys
modified = {o : (d1[o], d2[o]) for o in shared_keys if d1[o] != d2[o]}
same = set(o for o in shared_keys if d1[o] == d2[o])

x = dict(a=1, b=2)
y = dict(a=2, b=2)
added, removed, modified, same = dict_compare(x, y)
``````

# `dic1 == dic2`

From python docs:

The following examples all return a dictionary equal to
`{"one": 1, "two": 2, "three": 3}`:

``````>>> a = dict(one=1, two=2, three=3)
>>> b = {'one': 1, 'two': 2, 'three': 3}
>>> c = dict(zip(['one', 'two', 'three'], [1, 2, 3]))
>>> d = dict([('two', 2), ('one', 1), ('three', 3)])
>>> e = dict({'three': 3, 'one': 1, 'two': 2})
>>> a == b == c == d == e
True
``````

Providing keyword arguments as in the first example only works for
keys that are valid Python identifiers. Otherwise, any valid keys can
be used.

Valid for both `py2` and `py3`.

Since it seems nobody mentioned `deepdiff`, I will add it here for completeness. I find it very convenient for getting diff of (nested) objects in general:

### Installation

``````pip install deepdiff
``````

### Sample code

``````import deepdiff
import json

dict_1 = {
"a": 1,
"nested": {
"b": 1,
}
}

dict_2 = {
"a": 2,
"nested": {
"b": 2,
}
}

diff = deepdiff.DeepDiff(dict_1, dict_2)
print(json.dumps(diff, indent=4))
``````

### Output

``````{
"values_changed": {
"root['a']": {
"new_value": 2,
"old_value": 1
},
"root['nested']['b']": {
"new_value": 2,
"old_value": 1
}
}
}
``````

Note about pretty-printing the result for inspection: The above code works if both dicts have the same attribute keys (with possibly different attribute values as in the example). However, if an `"extra"` attribute is present is one of the dicts, `json.dumps()` fails with

``````TypeError: Object of type PrettyOrderedSet is not JSON serializable
``````

Solution: use `diff.to_json()` and `json.loads()` / `json.dumps()` to pretty-print:

``````import deepdiff
import json

dict_1 = {
"a": 1,
"nested": {
"b": 1,
},
"extra": 3
}

dict_2 = {
"a": 2,
"nested": {
"b": 2,
}
}

diff = deepdiff.DeepDiff(dict_1, dict_2)
``````

Output:

``````{
"dictionary_item_removed": [
"root['extra']"
],
"values_changed": {
"root['a']": {
"new_value": 2,
"old_value": 1
},
"root['nested']['b']": {
"new_value": 2,
"old_value": 1
}
}
}
``````

Alternative: use `pprint`, results in a different formatting:

``````import pprint

# same code as above

pprint.pprint(diff, indent=4)
``````

Output:

``````{   'dictionary_item_removed': [root['extra']],
'values_changed': {   "root['a']": {   'new_value': 2,
'old_value': 1},
"root['nested']['b']": {   'new_value': 2,
'old_value': 1}}}
``````

I’m new to python but I ended up doing something similar to @mouad

``````unmatched_item = set(dict_1.items()) ^ set(dict_2.items())
len(unmatched_item) # should be 0
``````

The XOR operator (`^`) should eliminate all elements of the dict when they are the same in both dicts.

Just use:

``````assert cmp(dict1, dict2) == 0
``````

@mouad ‘s answer is nice if you assume that both dictionaries contain simple values only. However, if you have dictionaries that contain dictionaries you’ll get an exception as dictionaries are not hashable.

Off the top of my head, something like this might work:

``````def compare_dictionaries(dict1, dict2):
if dict1 is None or dict2 is None:
print('Nones')
return False

if (not isinstance(dict1, dict)) or (not isinstance(dict2, dict)):
print('Not dict')
return False

shared_keys = set(dict1.keys()) & set(dict2.keys())

if not ( len(shared_keys) == len(dict1.keys()) and len(shared_keys) == len(dict2.keys())):
print('Not all keys are shared')
return False

dicts_are_equal = True
for key in dict1.keys():
if isinstance(dict1[key], dict) or isinstance(dict2[key], dict):
dicts_are_equal = dicts_are_equal and compare_dictionaries(dict1[key], dict2[key])
else:
dicts_are_equal = dicts_are_equal and all(atleast_1d(dict1[key] == dict2[key]))

return dicts_are_equal
``````