简体   繁体   中英

Compare two dictionaries with list of values which satisfies multiple conditions

I would like to compare two dictionaries that have list of values as follows:

dict1 = {'111': [], '333': ['a@a.com'], '444': ['b@b.com', 'c@c.com'], '555': ['d@d.com']}
dict2 = {'111': ['e@e.com'], '333': ['f@f.com' ], '444': ['b@b.com', 'g@g.com'], '555': ['d@d.com']}

and create a resultant dict (result_dict) that satisfies the following conditions:

  1. dict2 values that are not present in dict1 for the specific key add to result_dict
  2. if values for dict1 and dict2 are the same then that key need not be added in result_dict(For eg 555 should be skipped)

The resultant dict should look as follows:

   dict3 = {'1111': ['e@e.com'], '333': ['f@f.com'], '444': ['g@g.com']}

I have the following code

    result_dict = {}
    for k,v in dict2.items():
        for k1,v1 in dict1.items():
            if k == k1 and v != v1:
               result_dict[k] = v


    print(result_dict)

Which outputs:

{'111': ['e@e.com'], '333': ['f@f.com'], '444': ['b@b.com', 'g@g.com']}

In the above case it should not have added 'b@b.com' for 444. It also gives incorrect result if the order is changed for eg

'444': ['b@b.com', 'c@c.com']
'444': ['c@c.com', 'b@b.com']

Sorting dict values will not help, coz there will be scenarios where dict1 has more values than dict2 for ceratin keys. I am using Python 3.7. Any help would be greatly appreciated

If you want to keep the same order in the result_dict as in the original dict ( dict2 , I mean):

result_dict = {
    k: v if k not in dict1 else [a for a in v if a not in dict1[k]]
    for k, v in filter(lambda x: len(set(x[1]).difference(dict1.get(x[0], []))), dict2.items())
}

Here result_dict :

{'111': ['e@e.com'], '333': ['f@f.com'], '444': ['g@g.com']}

The output dict is created by a dict comprehension . Basically, we select keys in dict2 whose values are lists with at least one original element compared to the correspondent lists in dict1 . Then, lists of the selected keys are cleaned, removing elements also present in the correspondent lists in dict1 . In particular:

  • filter(lambda x: len(set(x[1]).difference(dict1.get(x[0], []))), dict2.items()) } : only loop over the pairs key/list of dict2 having at least one element that is not in the correspondent list of dict1 .
  • k: v if k not in dict1 else [a for a in v if a not in dict1[k]] create an entry in the new dict with the same key of dict2 and as value the corresponding list in dict2 , if the key in not in dict1 , else create a new list (with list comprehension ) looping over the item in the list of dict2 and removing those also in the correspondent list in dict1 (this will preserve the order of the original list in dict2 .

You can filter out any of the items who's values match, then within a dict comprehension the new keys should be the set.difference for the corresponding keys.

>>> {k:list(set(v).difference(dict1[k])) for k,v in dict2.items() if dict1[k] != v}
{'111': ['e@e.com'], '333': ['f@f.com'], '444': ['g@g.com']}

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