HimanAB
HimanAB

Reputation: 2573

How to find the difference between two lists that contain lists in Python?

If we have

X1=[[a,b,c],[a,e,t],[a,b,c]] 

and

X2=[[a,b,c]] 

I want to find the difference between X1 and X2 which is:

X3=X1-X2=[[a,b,c],[a,e,t]].

So my output should contain two lists not one as I only want to remove one [a,b,c] not both.

I am doing it in this way but I get error:

s = set(X2)
X3 = [x for x in X1 if x not in s]

The error I get is this:

unhashable type: 'list'

I get this error when the program get to this point:

s = set(X2)

Upvotes: 1

Views: 132

Answers (3)

Moses Koledoye
Moses Koledoye

Reputation: 78556

lists are unhashable so they cannot be members of a set. You can convert the inner lists into a frozenset, so two sublists with the same items but different ordering are still considered same and then use a Counter to find the difference between both lists:

from collections import Counter

X3 = Counter([frozenset(i) for i in X1]) - Counter([frozenset(i) for i in X2])
print(X3)
# Counter({frozenset({'c', 'a', 'b'}): 1, frozenset({'e', 'a', 't'}): 1})

print(X3.keys())
# [frozenset({'e', 't', 'a'}), frozenset({'c', 'b', 'a'})]

A Counter is a subclass of a dict, so you can return the difference as a list by using .keys():

print(X3.keys()) # or print(list(X3.keys())) in Python 3.x
# [frozenset({'e', 't', 'a'}), frozenset({'c', 'b', 'a'})]

If you need to keep your inner lists, you can replace the frozenset with lists by doing:

X3 = [list(i) for i in X3.keys()]

print(X3)
# [['a', 't', 'e'], ['c', 'a', 'b']]

Upvotes: 1

harshit-sh
harshit-sh

Reputation: 386

So, X3 = [a,e,t], right?

There is no need to convert it to set. You can do this:

result = [x for x in X1 if x not in X2].

Upvotes: 4

Blender
Blender

Reputation: 298186

As the error states, lists are unhashable (because they're mutable). Convert your list of lists into a list of tuples, which are hashable:

>>> hash((1, 2, 3))
2528502973977326415
>>> hash([1, 2, 3])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

In your case, you could do:

s = set(map(tuple, X2))

Upvotes: 0

Related Questions