Skip to content Skip to sidebar Skip to footer

Find Unique (key: Value) Pair Given N Dictionaries In Python

I would like to find an easy and/or fast way to find all common couple (pair: value) given N dictionaries in python. (3.X would be best) PROBLEM Given a set of 3 dicts (but it coul

Solution 1:

Simpler and more efficient way:

>>> {k: v
     for k, v in list_dict[0].items()
     ifall(k in d and d[k] == v
            for d in list_dict[1:])}
{'c': 3, 'a': 1}

Using an extra variable for list_dict[1:] might be beneficial, otherwise the short-circuiting of all somewhat goes to waste. Or if you don't need the list afterwards you could just pop the "master" dictionary:

>>> {k: v
     for k, v in list_dict.pop().items()
     ifall(k in d and d[k] == v
            for d in list_dict)}
{'c': 3, 'a': 1}

Or using get with a default that cannot be in the dictionary as suggested by @Jean-FrançoisFabre:

>>> marker = object()
>>> {k: v
         for k, v in list_dict.pop().items()
         ifall(d.get(k, marker) == v
                for d in list_dict)}
{'c': 3, 'a': 1}

Solution 2:

If unhashable values are a problem you can always compute the intersection of the keys up-front by using .keys() and then compare only the values associated with the keys that all dictionaries have in common:

import operator as op
from functools import reduce

common_keys = reduce(op.and_, (d.keys() for d in my_dicts))
common_items = {}
for key in common_keys:
    value = my_dicts[0][key]
    ifall(d[key] == value for d in my_dicts):
        common_items[key] = value

This should be pretty faster than solution a, slower than solution b, but works on all inputs.

Solution 3:

A batteries-included version.

To handle unhashable types, we use pickling; replace it with dill or json or any other predictable serialization to taste.

import collections
import itertools
import pickle  

deffindCommonPairs(dicts):
    all_pairs = itertools.chain(*[d.items() for d in dicts])
    cnt = collections.Counter(map(pickle.dumps, all_pairs))
    return [pickle.loads(pickled_pair)
            for pickled_pair, count in cnt.items()
            if count == len(dicts)]


>>> findCommonPairs([n1, n2, n3])
[('a', 1), ('c', 3)]

>>> findCommonPairs([{'a': [1,2], 'b': [2,3]}, {'a': [1,2]}])
[('a', [1, 2])]

Note that serialization only goes so far. To properly compare dicts if dicts, for instance, these dicts must be turned into (key, value) pairs and sorted before serialization. Any structures that reference each other may have issues (or not). Replace pickling with a custom predictable serializer if you care about these issues.

Post a Comment for "Find Unique (key: Value) Pair Given N Dictionaries In Python"