Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: Find difference between two dictionaries containing lists

I have two dictionaries that have the following structure:

a = {'joe': [24,32,422], 'bob': [1,42,32,24], 'jack':[0,3,222]}
b = {'joe': [24], 'bob': [1,42,32]}

I would like to retrieve the difference between these two dictionaries which in this case would result as:

{'joe': [32,422], 'bob': [24], 'jack':[0,3,222]}

I know that I could do this with a messy loop, but I would like to know how can I achieve this in a clean, pythonic fashion?

I did try: a.items() - b.items()

but I get the following error: unsupported operand type(s) for -: 'dict_values' and 'dict_values'

Thanks for your help

like image 226
Ryan Avatar asked Dec 15 '15 20:12

Ryan


2 Answers

Assuming that there would be no duplicate entries in any of your lists, you can do what you want with sets but not with lists:

>>> a = {'joe': [24,32,422], 'bob': [1,42,32,24], 'jack':[0,3,222]}
>>> b = {'joe': [24], 'bob': [1,42,32]}
>>> {key: list(set(a[key])- set(b.get(key,[]))) for key in a}
{'joe': [32, 422], 'bob': [24], 'jack': [0, 3, 222]}

Note two things:

  • I convert the set back to a list when I set it as the value
  • I use b.get rather than b[key] to handle if the key does not exist in b, but does in a

EDIT - using a for loop:

I realized that the comprehension may not be that self explanatory so this is an equivalent bit of code using a for loop:

>>> c = {}
>>> for key in a:
    c[key] = list(set(a[key]) - set(b.get(key,[])))


>>> c
{'joe': [32, 422], 'bob': [24], 'jack': [0, 3, 222]}

EDIT - lose the second set:

As Padraic Cunningham mentioned in the comments (as he so often does, bless his soul), you can make use of set.difference to avoid explicitly casting your second list to a set:

>>> c = {}
>>> for key in a:
    c[key] = list(set(a[key]).difference(b.get(key,[])))


>>> c
{'joe': [32, 422], 'bob': [24], 'jack': [0, 3, 222]}

or with list comprehension:

>>> {key: list(set(a[key]).difference(b.get(key,[]))) for key in a}
{'joe': [32, 422], 'bob': [24], 'jack': [0, 3, 222]}

or if you want to treat set.difference as a class method instead of an instance method:

>>> {key: list(set.difference(set(a[key]),b.get(key,[]))) for key in a}
{'joe': [32, 422], 'bob': [24], 'jack': [0, 3, 222]}

Though I find this a tad bit clunky and I don't really like it as much.

like image 148
R Nar Avatar answered Sep 20 '22 12:09

R Nar


You need to use sets:

diff = {}
for key in a:
    diff[key] = list(set(a[key]) - set(b.get(key, [])))
print diff
like image 39
Ali Nikneshan Avatar answered Sep 20 '22 12:09

Ali Nikneshan