it-swarm.com.de

Python: TypeError: Unhashable Typ: 'Liste'

Ich versuche, eine Datei mitzunehmen, die so aussieht

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

Und verwenden Sie ein Wörterbuch, damit die Ausgabe so aussieht

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

Das habe ich versucht

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

Ich bekomme immer einen TypeError: unhashable type: 'list'. Ich weiß, dass Schlüssel in einem Wörterbuch keine Listen sein können, aber ich versuche, meinen Wert in eine Liste und nicht in den Schlüssel zu bringen. Ich frage mich, ob ich irgendwo einen Fehler gemacht habe.

55
Keenan

Wie in den anderen Antworten angegeben, liegt der Fehler an k = list[0:j], wo Ihr Schlüssel in eine Liste umgewandelt wird. Sie könnten versuchen, Ihren Code zu überarbeiten, um die split-Funktion zu nutzen:

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

Wenn Sie Python 3.x verwenden, müssen Sie eine geringfügige Anpassung vornehmen, damit es ordnungsgemäß funktioniert. Wenn Sie die Datei mit rb öffnen, müssen Sie line = line.split(b'x') verwenden (um sicherzustellen, dass Sie das Byte mit dem richtigen String-Typ teilen). Sie können die Datei auch mit with open('filename.txt', 'rU') as f: (oder sogar with open('filename.txt', 'r') as f:) öffnen, und es sollte funktionieren.

34
RocketDonkey

Sie versuchen, k (eine Liste) als Schlüssel für d zu verwenden. Listen sind veränderbar und können nicht als Diktiertasten verwendet werden.

Aufgrund dieser Zeile initialisieren Sie auch niemals die Listen im Wörterbuch:

if k not in d == False:

Welches sollte sein:

if k not in d == True:

Was sollte eigentlich sein:

if k not in d:
11
Jesse the Game

Hinweis: Diese Antwort beantwortet die gestellte Frage nicht explizit. Die anderen Antworten tun es. Da es sich bei der Frage um zu einem Szenario handelt und die angehobene Ausnahme allgemein ist , Diese Antwort zeigt auf den allgemeinen Fall.

Hash-Werte sind nur Ganzzahlen, die verwendet werden, um Wörterbuchschlüssel während einer Wörterbuchsuche schnell zu vergleichen.

Intern ruft die hash()-Methode die __hash__()-Methode eines Objekts auf, die standardmäßig für jedes Objekt festgelegt ist.

Eine verschachtelte Liste in eine Menge konvertieren

>>> a = [1,2,3,4,[5,6,7],8,9]
>>> set(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

Dies geschieht aufgrund der Liste innerhalb einer Liste, die nicht gehasht werden kann. Welches Problem gelöst werden kann durch Konvertieren der internen verschachtelten Listen in ein Tuple,

>>> set([1, 2, 3, 4, (5, 6, 7), 8, 9])
set([1, 2, 3, 4, 8, 9, (5, 6, 7)])

Explizites Hashing von einer verschachtelten Liste

>>> hash([1, 2, 3, [4, 5,], 6, 7])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'


>>> hash(Tuple([1, 2, 3, [4, 5,], 6, 7]))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

>>> hash(Tuple([1, 2, 3, Tuple([4, 5,]), 6, 7]))
-7943504827826258506

Die Lösung, um diesen Fehler zu vermeiden, besteht darin, die Liste neu zu strukturieren, um geschachtelte Tupel anstelle von Listen zu haben.

7

Der Grund, warum Sie die unhashable type: 'list'-Ausnahme erhalten, ist, dass k = list[0:j]k als "Slice" der Liste definiert, was logischerweise eine andere, häufig kürzere Liste ist. Sie müssen nur das erste Element in der Liste erhalten, das wie k = list[0] geschrieben wird. Dasselbe gilt für v = list[j + 1:], das nur v = list[2] für das dritte Element der Liste sein sollte, das vom Aufruf an readline.split(" ") zurückgegeben wurde.

Ich habe einige andere wahrscheinliche Probleme mit dem Code festgestellt, von denen ich einige erwähnen möchte. Eine große Sache ist, dass Sie d nicht mit d = {} für jede in der Schleife gelesene Zeile (neu) initialisieren möchten. Ein anderer Grund ist, dass es im Allgemeinen keine gute Idee ist, Variablen genauso zu benennen wie andere eingebaute Typen, da dies den Zugriff auf eine von ihnen verhindern kann, wenn Sie sie benötigen. Dies ist verwirrend für andere, die es gewohnt sind Namen, die einen dieser Standardartikel kennzeichnen. Aus diesem Grund sollten Sie die Variable list in etwas anderes umbenennen, um Probleme wie diese zu vermeiden.

Hier ist eine funktionierende Version von Ihnen mit diesen Änderungen. Ich habe auch den if-Anweisungsausdruck vereinfacht, mit dem Sie überprüfen, ob der Schlüssel bereits im Wörterbuch vorhanden ist Bedingungsanweisung ist für jetzt in Ordnung.

d = {}
file = open("filename.txt", "r")
readline = file.readline().rstrip()
while readline:
    lst = readline.split(" ") # Split into sequence like ['AAA', 'x', '111'].
    k = lst[0]  # First item.
    v = lst[2]  # Third item.
    if k not in d:  # New key?
        d[k] = []  # Initialize its associated value to an empty list.
    d[k].append(v)
    readline = file.readline().rstrip()

file.close()  # Done reading file.
print('d: {}'.format(d))

Ausgabe:

d: {'AAA': ['111', '112'], 'AAC': ['123'], 'AAB': ['111']}
4
martineau

Die Variable TypeError geschieht, weil k eine Liste ist, da sie mit einem Slice aus einer anderen Liste mit der Zeile k = list[0:j] erstellt wird. Dies sollte wahrscheinlich etwas wie k = ' '.join(list[0:j]) sein, daher haben Sie stattdessen eine Zeichenfolge.

Darüber hinaus ist Ihre if-Anweisung falsch, wie von Jesse's Antwort vermerkt, die if k not in d oder if not k in d lauten sollte (ich bevorzuge die letztere).

Sie löschen auch bei jeder Iteration Ihr Wörterbuch, da Sie d = {} in Ihrer for-Schleife haben.

Beachten Sie, dass Sie auch nicht list oder file als Variablennamen verwenden sollten, da Sie eingebaute Objekte maskieren.

So würde ich Ihren Code umschreiben:

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

Die dict.setdefault()-Methode oben ersetzt die if k not in d-Logik aus Ihrem Code.

0
Andrew Clark