Search code examples
pythonlist-comparison

Is there any Python module can be adopted for [{},{}...] comparation?


It's intended to compare two lists in Python which are made up of dict elements, in each dict element, there are two keys. Below the sample is provided.

A=[{'id':'u2s8Et','value':'David'},{'id':'u2s0PW','value':'Linda'},......]
B=[{'id':'u2s8Et','value':'David'},{'id':'u2s7PA','value':'Steven'},......]

It's expected to get which elements are only available in list A and which elements in list A differ from the one in list B. Is there any existing module can be adopted to compare?

The method assertListEqual in unittest module is close to the expectation but some module more comprehensive is preferred.


Solution

  • The main issue is that dicts are not hashable. Because each one of them has the same keys, though, we can convert them to a hashable type, like a tuple.

    def parse(values):
        return set(map(tuple, map(dict.values, values)))
    
    >>> parse(A)
    >>> {('u2s0PW', 'Linda'), ('u2s8Et', 'David')}
    

    We can now use set operations to compare the elements of each.

    In [6]: parse(A).difference(parse(B))
    Out[6]: {('u2s0PW', 'Linda')}
    
    In [7]: parse(A).intersection(parse(B))
    Out[7]: {('u2s8Et', 'David')}
    

    set.difference will find the items that are in A but not B, and set.intersection will find the items that are in both A and B.


    Edit: Since your dicts all follow the same format, you could consider using a namedtuple, as well.

    In [1]: from collections import namedtuple
    
    In [2]: entry = namedtuple("Entry", ("id", "value"))
    
    In [3]: A = [{'id':'u2s8Et', 'value':'David'}, {'id':'u2s0PW', 'value':'Linda'}]
       ...: B = [{'id':'u2s8Et', 'value':'David'}, {'id':'u2s7PA', 'value':'Steven'}]
       ...: 
    
    In [4]: def parse_to_entry(values):
       ...:     return {entry(d["id"], d["value"]) for d in values}
       ...: 
    
    In [5]: parse_to_entry(A)
    Out[5]: {Entry(id='u2s0PW', value='Linda'), Entry(id='u2s8Et', value='David')}
    
    In [6]: parse_to_entry(A).difference(parse_to_entry(B))
    Out[6]: {Entry(id='u2s0PW', value='Linda')}
    
    In [7]: parse_to_entry(A).intersection(parse_to_entry(B))
    Out[7]: {Entry(id='u2s8Et', value='David')}