2016-07-01 3 views
0

Если мы имеемКак найти разницу между двумя списками, содержащими списки в Python?

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

и

X2=[[a,b,c]] 

Я хочу, чтобы найти разницу между X1 и X2, который:

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

Так что мой вывод должен содержать два списка не один, как Я только хочу удалить один [a, b, c] не оба.

Я делаю это таким образом, но я получаю сообщение об ошибке:

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

Ошибка я получаю это:

unhashable type: 'list' 

Я получаю эту ошибку, когда программа добраться до этой точки:

s = set(X2) 
+0

Какая ценность 'X3'? –

+0

X3 должен быть [[a, b, c], [a, e, t]], поскольку я хочу, чтобы только один [a, b, c] был удален из X1 не для обоих. – HimanAB

ответ

0

Как указано в сообщении об ошибках, списки расщепляются (поскольку они изменяемы). Преобразование списка списков в список кортежей, которые 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' 

В вашем случае, вы могли бы сделать:

s = set(map(tuple, X2)) 
+0

Или 'set = {tuple (подсписка) для подписок в X2}', если вы предпочитаете понимание. – Daerdemandt

+0

@Daerdemandt, так как карта не связана с лямбдой, это, вероятно, быстрее. Кроме того, он намного чище/читабельнее. – Jeremy

+0

Да, карты обычно быстрее. Тем не менее многие люди все же предпочитают понимание. Что касается «намного более чистого/читаемого», это субъективно. – Daerdemandt

4

Так, X3 = [a,e,t], верно?

Нет необходимости преобразовывать его в набор. Вы можете сделать это:

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

+0

Это не удастся, если порядок элементов в подсписках не одинаковый. –

+0

X3 должен быть [[a, b, c], [a, e, t]], поскольку я хочу только один [a, b, c] быть удалены из X1 не оба. – HimanAB

+0

Ну ладно, тогда вы должны обновить свой вопрос с помощью этой информации. –

1

списки: unhashable поэтому они не могут быть членами set. Вы можете преобразовать внутренние списки в frozenset, так что два подсписки с теми же элементами, но разной упорядоченностью по-прежнему считаются одинаковыми и затем использовать Counter найти разницы между двумя списками:

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'})] 

Counter является подкласс dict, так что вы можете вернуть разницу в виде списка с помощью .keys():

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

Если вам нужно сохранить свои внутренние list с, вы можете заменить frozenset со списками справляюсь ing:

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

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

X3 должен быть [[a, b, c], [a, e, t]], поскольку я хочу, чтобы только один [a, b, c] был удален из X1 не для обоих. – HimanAB

+0

@HimanUCC См. Мое обновление –

+0

Это даже не дает мне список – HimanAB