167 votes

Comment surmonter l'erreur de type : unhashable type : 'list'.

J'essaie de prendre un fichier qui ressemble à ça :

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

Et utiliser un dictionnaire pour que la sortie ressemble à ceci

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

Voici ce que j'ai essayé

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

Je continue de recevoir un TypeError: unhashable type: 'list' . Je sais que les clés d'un dictionnaire ne peuvent pas être des listes mais j'essaie de faire de ma valeur une liste et non la clé. Je me demande si je n'ai pas fait une erreur quelque part.

80voto

RocketDonkey Points 16205

Comme indiqué par les autres réponses, l'erreur est due à k = list[0:j] où votre clé est convertie en une liste. Une chose que vous pourriez essayer est de retravailler votre code pour tirer profit de la fonction split función:

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

Notez que si vous utilisez Python 3.x, vous devrez faire un petit ajustement pour que cela fonctionne correctement. Si vous ouvrez le fichier avec rb vous devrez utiliser line = line.split(b'x') (qui s'assure que vous divisez l'octet avec le bon type de chaîne). Vous pouvez également ouvrir le fichier en utilisant with open('filename.txt', 'rU') as f: (ou même with open('filename.txt', 'r') as f: ) et cela devrait fonctionner correctement.

79voto

Marty Points 1097

Note : Cette réponse ne répond pas explicitement à la question posée. Les autres réponses le font. Puisque la question est spécifique à un scénario et le relevé l'exception est générale Cette réponse indique le cas général.

Les valeurs de hachage sont simplement des entiers qui sont utilisés pour comparer rapidement les clés d'un dictionnaire lors d'une consultation de celui-ci.

En interne, hash() appels de méthodes __hash__() d'un objet qui sont définies par défaut pour tout objet.

Convertir d'une liste imbriquée à un ensemble

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

Cela se produit à cause de la liste à l'intérieur d'une liste qui est une liste qui ne peut pas être hachée. Ce qui peut être résolu par convertir les listes internes imbriquées en un tuple ,

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

Hachage explicite une liste imbriquée

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

La solution pour éviter cette erreur est de restructurer la liste pour avoir des tuples imbriqués au lieu de listes.

28voto

Jesse the Game Points 2504

Vous essayez d'utiliser k (qui est une liste) comme une clé pour d . Les listes sont mutables et ne peuvent pas être utilisées comme clés de dict.

De plus, vous n'initialiserez jamais les listes dans le dictionnaire, à cause de cette ligne :

if k not in d == False:

Ce qui devrait être :

if k not in d == True:

Ce qui devrait être en fait :

if k not in d:

6voto

martineau Points 21665

La raison pour laquelle vous obtenez le unhashable type: 'list' L'exception est due au fait que k = list[0:j] fixe k pour être une "tranche" de la liste, qui est logiquement une autre liste, souvent plus courte. Ce dont vous avez besoin, c'est de récupérer uniquement le premier élément de la liste, comme suit k = list[0] . Il en va de même pour v = list[j + 1:] qui devrait simplement être v = list[2] pour le troisième élément de la liste retournée par l'appel à readline.split(" ") .

J'ai remarqué plusieurs autres problèmes probables avec le code, dont je vais mentionner quelques-uns. L'un des plus importants est que vous ne voulez pas (ré)initialiser d con d = {} pour chaque ligne lue dans la boucle. D'autre part, ce n'est généralement pas une bonne idée de nommer les variables de la même façon que l'un des types intégrés, car cela vous empêchera d'accéder à l'un d'entre eux si vous en avez besoin - et c'est déroutant pour les autres qui sont habitués aux noms désignant l'un de ces éléments standard. Pour cette raison, vous devriez renommer votre variable list variable quelque chose de différent pour éviter ce genre de problèmes.

Voici une version de travail de votre avec ces changements, j'ai également remplacé le bouton if que vous utilisiez pour vérifier si la clé se trouvait déjà dans le dictionnaire et que vous utilisiez maintenant l'expression de l'instruction setdefault() pour accomplir la même chose de manière un peu plus succincte.

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

Sortie :

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

2voto

Rishabh Sinha Points 21

La raison en est que la liste contient une liste de valeurs. Comme :

a = [[1,2],[1,2],[3,4]]

Et ça ne marchera pas avec quelque chose comme ça :

list(set(a))

Pour résoudre ce problème, vous pouvez transformer la liste intérieure en tuple, comme :

a = [(1,2),(1,2),(3,4)]

Cela va fonctionner !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X