Python: TypeError: unhashable type: 'list'

I'm încearcă să ia un fișier care arată ca aceasta

AAA x 111
AAB x 111
AAA x 112
AAC x 123
...

Și folosiți un dicționar pentru ca rezultatul să arate astfel

{AAA: ['111', '112'], AAB: ['111'], AAC: [123], ...}

Aceasta este ceea ce am încercat

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

Continui să primesc un TypeError: unhashable type: 'list'. Știu că cheile dintr-un dicționar nu pot fi liste, dar eu încerc să transform valoarea mea într-o listă, nu în cheie. Mă întreb dacă nu cumva am făcut o greșeală undeva.

Soluția

Așa cum au indicat și celelalte răspunsuri, eroarea se datorează k = list[0:j], unde cheia este convertită într-o listă. Un lucru pe care l-ați putea încerca este să vă refaceți codul pentru a profita de funcția split:

# Using with ensures that the file is properly closed when you're done
with open('filename.txt', 'rb') as f:
  d = {}
  # Here we use readlines() to split the file into a list where each element is a line
  for line in f.readlines():
    # Now we split the file on `x`, since the part before the x will be
    # the key and the part after the value
    line = line.split('x')
    # Take the line parts and strip out the spaces, assigning them to the variables
    # Once you get a bit more comfortable, this works as well:
    # key, value = [x.strip() for x in line] 
    key = line[0].strip()
    value = line[1].strip()
    # Now we check if the dictionary contains the key; if so, append the new value,
    # and if not, make a new list that contains the current value
    # (For future reference, this is a great place for a defaultdict :)
    if key in d:
      d[key].append(value)
    else:
      d[key] = [value]

print d
# {'AAA': ['111', '112'], 'AAC': ['123'], 'AAB': ['111']}

Rețineți că, dacă utilizați Python 3.x, va trebui să faceți o mică ajustare pentru a o face să funcționeze corect. Dacă deschideți fișierul cu rb, va trebui să folosiți line = line.split(b'x') (care se asigură că împărțiți octetul cu tipul corect de șir de caractere). Puteți, de asemenea, să deschideți fișierul folosind with open('nume fișier.txt', 'rU') ca f: (sau chiar with open('nume fișier.txt', 'r') ca f:) și ar trebui să funcționeze bine.

Comentarii (3)

Încerci să folosești k (care este o listă) ca o cheie pentru d. Listele sunt mutabile și nu pot fi folosite ca chei dict.

De asemenea, nu inițializați niciodată listele din dicționar, din cauza acestei linii:

if k not in d == False:

Care ar trebui să fie:

if k not in d == True:

Care ar trebui să fie de fapt:

if k not in d:
Comentarii (1)

Eroarea TypeError se întâmplă deoarece k este o listă, deoarece este creată folosind o felie dintr-o altă listă cu linia k = list[0:j]. Probabil că ar trebui să fie ceva de genul k = ' '.join(list[0:j]), astfel încât să aveți în schimb un șir de caractere.

În plus, afirmația dvs. if este incorectă, așa cum a fost observat de răspunsul lui Jesse's, care ar trebui să fie if k not in d sau if not k in d (îl prefer pe cel din urmă).

De asemenea, vă ștergeți dicționarul la fiecare iterație, deoarece aveți d = {} în interiorul buclei for.

Rețineți că nu ar trebui să folosiți list sau file ca nume de variabile, deoarece veți masca elementele construite.

Iată cum aș rescrie eu codul dumneavoastră:

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

Metoda dict.setdefault() de mai sus înlocuiește logica if k not in d din codul dumneavoastră.

Comentarii (3)