简体   繁体   中英

Python: How to compare two lists of dictionaries

Folks, Relative n00b to python, trying to find out the diff of two lists of dictionaries.

If these were just regular lists, I could create sets and then do a '-'/intersect operation.

However, set operation does not work on lists of dictionaries:

>>> l = []
>>> pool1 = {}
>>> l.append(pool1)
>>> s = set(l)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'

You need a "hashable" dictionary.

The items() attribute is a list of tuples. Make this a tuple() and you have a hashable version of a dictionary.

tuple( sorted( some_dict.items() ) )

You can define your own dict wrapper that defines __hash__ method:

class HashableDict(dict):
    def __hash__(self):
        return hash(tuple(sorted(self.items())))

this wrapper is safe as long as you do not modify the dictionary while finding the intersection.

Python won't allow you to use a dictionary as a key in either a set or dictionary because it has no default __hash__ method defined. Unfortunately, collections.OrderedDict is also not hashable. There also isn't a built-in dictionary analogue to frozenset . You can either create a subclass of dict with your own hash method, or do something like this:

>>> def dict_item_set(dict_list):
...    return set(tuple(*sorted(d.items())) for d in dict_list)
>>> a = [{1:2}, {3:4}]
>>> b = [{3:4}, {5:6}]
>>> dict(dict_item_set(a) - dict_item_set(b))
{1: 2}
>>> dict(dict_item_set(a) & dict_item_set(b))
{3: 4}

Of course, this is neither efficient nor pretty.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM