Próbuję pobrać plik, który wygląda następująco:
AAA x 111
AAB x 111
AAA x 112
AAC x 123
...
I użyj słownika, aby wynik wyglądał następująco
{AAA: ['111', '112'], AAB: ['111'], AAC: [123], ...}
To jest to, czego próbowałem
file = open("filename.txt", "r")
readline = file.readline().rstrip()
while readline!= "":
list = []
list = readline.split(" ")
j = list.index("x")
k = list[0:j]
v = list[j + 1:]
d = {}
if k not in d == False:
d[k] = []
d[k].append(v)
readline = file.readline().rstrip()
Ciągle otrzymuję TypeError: unhashable type: 'list'
. Wiem, że klucze w słowniku nie mogą być listami, ale próbuję przekształcić moją wartość w listę, a nie klucz. Zastanawiam się, czy gdzieś popełniłem błąd.
źródło
Próbujesz użyć
k
(czyli listy) jako klucza dod
. Listy są zmienne i nie mogą być używane jako klucze dyktowania.Ponadto nigdy nie inicjalizujesz list w słowniku z powodu tego wiersza:
if k not in d == False:
Który powinien być:
if k not in d == True:
Który właściwie powinien być:
if k not in d:
źródło
Powodem, dla którego otrzymujesz
unhashable type: 'list'
wyjątek, jest to, żek = list[0:j]
ustawiak
się jako „wycinek” listy, która jest logicznie kolejną, często krótszą listą. Potrzebujesz tylko pierwszej pozycji na liście, tak napisanejk = list[0]
. To samo, dlav = list[j + 1:]
którego powinno być tylkov = list[2]
dla trzeciego elementu listy zwróconego z wywołaniareadline.split(" ")
.Zauważyłem kilka innych prawdopodobnych problemów z kodem, z których kilka wymienię. Duży jeden jest nie chcą (re) zainicjować
d
zd = {}
dla każdej linii czytać w pętli. Innym jest to, że generalnie nie jest dobrym pomysłem nazywanie zmiennych tak samo jak wszystkie typy wbudowane, ponieważ uniemożliwi to dostęp do jednego z nich, jeśli tego potrzebujesz - i jest mylące dla innych, którzy są przyzwyczajeni do nazwy określające jeden z tych standardowych elementów. Z tego powodu powinieneś zmienić nazwęlist
zmiennej na inną, aby uniknąć takich problemów.Oto działająca wersja twojego z tymi zmianami. Zastąpiłem również
if
wyrażenie wyrażenia, którego użyłeś do sprawdzenia, czy klucz był już w słowniku, a teraz użyj metody słownika,setdefault()
aby osiągnąć to samo trochę bardziej zwięźle.d = {} with open("nameerror.txt", "r") as file: line = file.readline().rstrip() while line: lst = line.split() # Split into sequence like ['AAA', 'x', '111']. k, _, v = lst[:3] # Get first and third items. d.setdefault(k, []).append(v) line = file.readline().rstrip() print('d: {}'.format(d))
Wynik:
źródło
TypeError
Się dzieje, ponieważk
jest to lista, ponieważ jest tworzony przy użyciu plasterek z innej listy z liniik = list[0:j]
. Prawdopodobnie powinno to być coś w styluk = ' '.join(list[0:j])
, więc zamiast tego masz ciąg.Oprócz tego, twoje
if
stwierdzenie jest nieprawidłowe, jak zauważyła odpowiedź Jessego, która powinna brzmiećif k not in d
lubif not k in d
(wolę to drugie).Czyścisz również słownik po każdej iteracji, ponieważ masz
d = {}
wewnątrzfor
pętli.Zauważ, że nie powinieneś także używać
list
anifile
jako nazw zmiennych, ponieważ będziesz maskował wbudowane.Oto jak przepisałbym twój kod:
d = {} with open("filename.txt", "r") as input_file: for line in input_file: fields = line.split() j = fields.index("x") k = " ".join(fields[:j]) d.setdefault(k, []).append(" ".join(fields[j+1:]))
Powyższa
dict.setdefault()
metoda zastępujeif k not in d
logikę z kodu.źródło
not k in d
może zmylić nowicjusza(not k) in d
, ponieważk not in d
nie ma dwuznacznościnot in
jest wymieniony jako operator .!a.contains(b)
.not in
może być bardziej pythonowe, po prostu uważam, że koncepcja dwóch operatorów słów jest bardziej zagmatwana niż użycie odwrotności w wyrażeniu boolowskim.python 3.2 with open("d://test.txt") as f: k=(((i.split("\n"))[0].rstrip()).split() for i in f.readlines()) d={} for i,_,v in k: d.setdefault(i,[]).append(v)
źródło