2016-03-22 17 views
5

mam tego słownika:typ Unhashable: „lista” błąd w Pythonie

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

Chciałem przekonwertować go na liście, więc użyłem listowych, a wynik był następujący:

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]] 

chciałem też całą listę, jak również elementów wewnątrz każdej małej wykazie sortowane i aby usunąć duplikaty z listy:

for i in myList: 
    i.sort() 

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

Jednak po uruchomieniu otrzymuję komunikat "Unhashable type: 'list' ". Czy istnieje inny sposób na wdrożenie tego? Z góry dziękuję!

Odpowiedz

3

Lista jest zmienna; w Pythonie zmienne kontenery nie są nieszczelne. set z kolei równa się elementom, które mają być nieaktualne. można przekonwertować list do krotek, które są niezmienne pojemniki i tym samym 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)] 

Zauważmy, że zbiory nie są klasyfikowane tak, że prawdopodobnie chcesz sortować po tworzenia zestawu:

>>> 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

A set potrzebuje listy obiektów mieszczenie; to znaczy, że są one niezmienne i nie zmieniają się po utworzeniu. Obiekt list jest zmienny zmienny, ponieważ może się zmienić (jak pokazano za pomocą funkcji sort, która na stałe zmienia kolejność listy), co oznacza, że ​​nie jest on zgodny, więc nie działa z set.

Rozwiązaniem tego problemu jest zamiana obiektów list na obiekty tuple; Te będą działać z set, ponieważ są nieosiągalne. Można to zrobić poprzez stworzenie generatora które następnie przejść do ustawienia:

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

krotki pracę w sposób podobny do wykazów, więc nie powinno to spowodować żadnych problemów z istniejącego programu. Jeśli nie potrzebować listę list choć można przekonwertować go z powrotem za pomocą listy ze zrozumieniem tak:

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

Jasne. Zmiana:

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

Do:

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

Stwarza to krotki zamiast listy dla kombinacji kluczy i wartości słownikowych. Krotki są niezmienne i mogą być używane jako wartości w zestawach, natomiast listy nie.

0

myList to lista list. Podczas budowania zestawu elementy zestawu muszą być niezmienne, aby zestawy działały poprawnie.

W tym przypadku listy są zmienne (możesz append lub remove pozycji), jest to konieczne dla zestawów powodu, jeśli możesz zmienić zawartość list Pythona nie będzie w stanie powiedzieć, czy Twój zestaw ma powtarzające się elementy, czy nie .

Wyobraźmy sobie tę sprawę (nie jest to możliwe, ale to sobie wyobrazić):

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 należy wnioskować, że chcesz L1 lub L2 być wyeliminowany z zestawu? Który? Czemu?

Jedną rzeczą, jaką można zrobić, to użyć krotki zamiast list (które są niezmienne wersja list) i przekształcić ją w zestawach

-1

Jeśli sortowania tylko listy zagnieżdżone usunięcie powtórzeń można użyć frozensets zamiast i uniknąć sortowanie:

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()})) 

Który daje:

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

można jeszcze SOR t pozostałe podlisty, które wciąż będą szybsze niż ich sortowanie, a następnie usuwanie, szczególnie jeśli podlisty są duże i/lub masz dużo duplikatów.

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

print(unique) 

które dadzą wam nakazał wyjście jeśli konieczne:

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

Ciekawe downvote za najbardziej efektywny odpowiedź. –

Powiązane problemy