Chris
Chris

Reputation: 5804

How to find the difference between two lists of dictionaries?

I have two lists of dictionaries and I'd like to find the difference between them (i.e. what exists in the first list but not the second, and what exists in the second list but not the first list).

The issue is that it is a list of dictionaries

a = [{'a': '1'}, {'c': '2'}]
b = [{'a': '1'}, {'b': '2'}]

set(a) - set(b)

Result

TypeError: unhashable type: 'dict'

Desired Result:

{'c': '2'}

How do I accomplish this?

Upvotes: 19

Views: 12094

Answers (3)

Padraic Cunningham
Padraic Cunningham

Reputation: 180391

You can also you filter with a lambda:

If you want the different items in each list:

print filter(lambda x: x not in b,a) + filter(lambda x: x not in a,b)

[{'c': '2'}, {'b': '2'}]

Or just filter(lambda x: x not in b,a) to get the elements in a but not in b If you don't want to create the full list of dicts in memory you can use itertools.ifilter

from itertools import ifilter

diff = ifilter(lambda x: x not in b,a)

Then just iterate over diff:

for uniq in diff:
   print uniq

Upvotes: 1

Sylvain Leroux
Sylvain Leroux

Reputation: 51990

I'd like to find the difference between them (i.e. what exists in the first list but not the second, and what exists in the second list but not the first list)

According to your definition, you looking for a Symmetric difference:

>>> import itertools

>>> a = [{'a': '1'}, {'c': '2'}]
>>> b = [{'a': '1'}, {'b': '2'}]
>>> intersec = [item for item in a if item in b]
>>> sym_diff = [item for item in itertools.chain(a,b) if item not in intersec]

>>> intersec
[{'a': '1'}]
>>> sym_diff
[{'c': '2'}, {'b': '2'}

Alternatively (using the plain difference as given in your example):

>>> a_minus_b = [item for item in a if item not in b]
>>> b_minus_a = [item for item in b if item not in a]
>>> sym_diff = list(itertools.chain(a_minus_b,b_minus_a))

>>> a_minus_b
[{'c': '2'}]
>>> b_minus_a
[{'b': '2'}]
>>> sym_diff
[{'c': '2'}, {'b': '2'}]

Upvotes: 4

Cory Kramer
Cory Kramer

Reputation: 117856

You can use the in operator to see if it is in the list

a = [{'a': '1'}, {'c': '2'}]
b = [{'a': '1'}, {'b': '2'}]

>>> {'a':'1'} in a
True
>>> {'a':'1'} in b
True

>>> [i for i in a if i not in b]
[{'c': '2'}]

Upvotes: 24

Related Questions