pythonlistdictionarycompare

Comparing 2 lists consisting of dictionaries with unique keys in python


I have 2 lists, both of which contain same number of dictionaries. Each dictionary has a unique key. There is a match for each dictionary of the first list in the second list, that is a dictionary with a unique key exists in the other list. But the other elements of such 2 dictionaries may vary. For example:

list_1 = [
            {
                'unique_id': '001',
                'key1': 'AAA',
                'key2': 'BBB',
                'key3': 'EEE'
             },
             {
                'unique_id': '002',
                'key1': 'AAA',
                'key2': 'CCC',
                'key3': 'FFF'
             }
         ]

 list_2 = [
             {
                'unique_id': '001',
                'key1': 'AAA',
                'key2': 'DDD',
                'key3': 'EEE'
             },
             {
                'unique_id': '002',
                'key1': 'AAA',
                'key2': 'CCC',
                'key3': 'FFF'
             }
         ]

I want to compare all elements of 2 matching dictionaries. If any of the elements are not equal, I want to print the none-equal elements.

Would you please help?


Solution

  • Assuming that the dicts line up like in your example input, you can use the zip() function to get a list of associated pairs of dicts, then you can use any() to check if there is a difference:

    >>> list_1 = [{'unique_id':'001', 'key1':'AAA', 'key2':'BBB', 'key3':'EEE'}, 
                  {'unique_id':'002', 'key1':'AAA', 'key2':'CCC', 'key3':'FFF'}]
    >>> list_2 = [{'unique_id':'001', 'key1':'AAA', 'key2':'DDD', 'key3':'EEE'},
                  {'unique_id':'002', 'key1':'AAA', 'key2':'CCC', 'key3':'FFF'}]
    >>> pairs = zip(list_1, list_2)
    >>> any(x != y for x, y in pairs)
    True
    

    Or to get the differing pairs:

    >>> [(x, y) for x, y in pairs if x != y]
    [({'key3': 'EEE', 'key2': 'BBB', 'key1': 'AAA', 'unique_id': '001'}, {'key3': 'EEE', 'key2': 'DDD', 'key1': 'AAA', 'unique_id': '001'})]
    

    You can even get the keys which don't match for each pair:

    >>> [[k for k in x if x[k] != y[k]] for x, y in pairs if x != y]
    [['key2']]
    

    Possibly together with the associated values:

    >>> [[(k, x[k], y[k]) for k in x if x[k] != y[k]] for x, y in pairs if x != y]
    [[('key2', 'BBB', 'DDD')]]
    

    NOTE: In case your input lists are not sorted yet, you can do that easily as well:

    >>> from operator import itemgetter
    >>> list_1, list_2 = [sorted(l, key=itemgetter('unique_id')) 
                          for l in (list_1, list_2)]