2016-03-22 14 views
5

Ich habe dieses Wörterbuch:Unhashable Typ: 'list' Fehler in Python

final = {0: [1, 9], 1: [0, 9], 8: [16, 10], 9: [0, 1], 10: [8, 16], 16: [8, 10]} 

Und ich wollte es in eine Liste konvertieren, so habe ich Listenkomprehensionen und das Ergebnis wurde die folgende:

myList = [[int(k)]+v for k, v in final.items()] 
myList = [[0, 1, 9], [0, 1, 9], [0, 1, 9], [8, 10, 16], [8, 10, 16], [8, 10, 16]] 

wollte ich auch die ganze Liste sowie die Elemente innerhalb jeder kleinen Liste sortiert werden und die Duplikate aus der Liste zu löschen:

for i in myList: 
    i.sort() 

myList.sort() 
list(set(myList)) 
print(myList) 

Wenn ich dies jedoch ausführen, erhalte ich den Fehler "Unhashable type: 'list' ". Gibt es eine andere Möglichkeit, dies zu implementieren? Vielen Dank im Voraus!

Antwort

3

Eine Liste ist änderbar; In Python sind veränderbare Container nicht hashbar. set wiederum reiht die Artikel als hashbar ein. Sie können die Listen zu Tupeln, die unveränderlich Behälter sind wandeln und somit hashable:

>>> myList = [[0, 1, 9], [0, 1, 9], [0, 1, 9], [8, 10, 16], [8, 10, 16], [8, 10, 16]] 
>>> list(set(tuple(i) for i in myList)) 
[(8, 10, 16), (0, 1, 9)] 

Beachten Sie, dass Sätze sind nicht sortiert, so dass Sie wahrscheinlich nach machen das Set sortieren wollen würde:

>>> myList = [[0, 1, 9], [0, 1, 9], [0, 1, 9], [8, 10, 16], [8, 10, 16], [8, 10, 16]] 
>>> sorted(set(tuple(i) for i in myList)) 
[(0, 1, 9), (8, 10, 16)] 
1

Eine set benötigt eine Liste von hashable Objekte; das heißt, sie sind unveränderlich und ihr Zustand ändert sich nicht, nachdem sie erstellt werden. Ein list Objekt ist veränderbar jedoch, weil es ändern kann (wie durch die sort Funktion angezeigt, die die Liste permanent neu anordnet) was bedeutet, dass es nicht hashbar ist, also nicht mit set funktioniert.

Die Lösung hierfür ist die list Objekte in tuple Objekte zu konvertieren; Diese werden mit set arbeiten, weil sie waschbar sind. Sie können dies tun, indem Sie einen Generator zu schaffen, die Sie dann setzen passieren:

>>> list(set(tuple(x) for x in myList)) 
[(0, 1, 9), (8, 10, 16)] 

Tupeln Arbeit in ähnlicher Weise wie Listen, so dass dies irgendwelche Probleme mit Ihrem bestehenden Programm nicht dazu führen sollte. Wenn Sie haben obwohl eine Liste von Listen benötigen, können Sie es durch die Verwendung einer Liste Verständnis, wie diese konvertieren zurück:

>>> [list(x) for x in set(tuple(x) for x in myList))] 
[[0, 1, 9], [8, 10, 16]] 
1

Sicher. Wechsel:

myList = [[int(k)]+v for k, v in final.items()] 

An:

myList = [tuple([int(k)]+v) for k, v in final.items()] 

Dadurch entsteht ein Tupel, anstatt eine Liste für Ihre Kombination von Dictionary-Schlüssel und Werte. Tupel sind unveränderlich und können als Werte in Mengen verwendet werden, während Listen nicht verwendet werden können.

0

myList ist eine Liste von Listen. Wenn Sie einen Satz erstellen, müssen die Elemente des Satzes unveränderlich sein, damit Sätze ordnungsgemäß funktionieren.

In diesem Fall Listen sind wandelbar (Sie können append oder remove Artikel), das notwendig ist für Mengen verursachen, wenn Sie den Inhalt der Listen Python, wenn Ihr Satz Elemente zu sagen, wäre nicht in der Lage ändern könnte oder nicht wiederholt .

Stellen Sie sich vor, diesen Fall (es ist nicht möglich, aber vorstellen, dass es):

l1 = [1,2,3] 
l2 = [1,2] 
s = set([l1, l2]) #Here both lists are different 
l2.append(3) #Here both lists are equal 

Python sollte daraus schließen, dass Sie L1 oder L2 wollen aus der Menge beseitigt werden? Welcher? Warum?

Eine Sache, die Sie tun können, ist die Verwendung Tupel statt Listen (die eine unveränderliche Version von Listen sind) und die wandeln es in Sätzen

-1

Wenn Sie nur die Unterlisten Sortierung Betrogenen entfernen Sie frozensets verwenden können statt und vermeiden Sortierung:

final = {0: [1, 9], 1: [0, 9], 8: [16, 10], 9: [0, 1], 10: [8, 16], 16: [8, 10]} 

unique = list(map(list, {frozenset([k] + v) for k, v in final.items()})) 

die Ihnen:

[[0, 1, 9], [16, 8, 10]] 

Sie könnten noch sor t die restlichen Unterlisten, die immer noch schneller sind, als sie alle zuerst zu sortieren und dann zu entfernen, besonders wenn die Unterlisten groß sind und/oder du viele Duplikate hast.

unique = list(map(sorted, {frozenset([k] + v) for k, v in final.items()})) 

print(unique) 

die Ihnen bestellten Ausgabe bei Bedarf:

[[0, 1, 9], [8, 10, 16]] 
+0

Interessante downvote für die effizienteste Lösung. –