Python: TypeError: unhashable type: 'list'

je suis en train de prendre un fichier qui ressemble à ça

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

Et utiliser un dictionnaire, de sorte que la sortie ressemble à ceci

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

C'est 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 n'arrête pas de recevoir une 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, pas la clé. Je me demande si j'ai fait une erreur quelque part.

Merci à tous ceux qui m'ont aidé avec ma dernière question.

45
demandé sur Keenan 2012-12-03 03:49:20

6 réponses

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

# 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, tu vas devoir faire un petit ajustement pour que ça marche correctement. Si vous ouvrez le fichier avec rb, vous aurez besoin d'utiliser line = line.split(b'x') (ce qui vous assure de partager le byte avec le type de chaîne approprié). Vous pouvez également ouvrir le fichier utilisant with open('filename.txt', 'rU') as f: (ou même with open('filename.txt', 'r') as f:) et il devrait fonctionner correctement.

28
répondu RocketDonkey 2012-12-03 00:53:40

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

aussi, vous n'initialisez 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:

Qui devrait en fait être:

if k not in d:
10
répondu Jesse the Game 2012-12-02 23:58:14

Remarque: Cette réponse ne répond pas explicitement à la question posée. les autres réponses ne. Puisque la question est spécifique scénario et la exception est en général, Cette réponse pour le cas général.

les valeurs de hachage sont juste des entiers qui sont utilisés pour comparer des clés de dictionnaire pendant une recherche de dictionnaire rapidement.

en Interne, hash() les appels de méthode __hash__() méthode d'un objet défini par défaut pour tout objet.

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

Ceci se produit en raison de la liste à l'intérieur d'une liste qui est une liste qui ne peut être haché. Qui peut être résolu par conversion des 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)])

Explicitement de hachage 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.

6
répondu All Іѕ Vаиітy 2018-07-16 10:32:40

La raison pour laquelle vous obtenez le unhashable type: 'list' exception est parce que k = list[0:j] configure k pour être une "tranche" de la liste, qui est logiquement un autre, souvent plus courte liste. Ce que vous avez besoin est d'obtenir juste le premier élément de la liste, écrit comme k = list[0]. De même pour v = list[j + 1:] qui devrait être v = list[2] pour la 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 en mentionner quelques-uns. Un grand c'est que vous n' souhaitez (ré)initialiser dd = {} pour chaque ligne lue dans la boucle. Une autre est que ce n'est généralement pas une bonne idée de nommer les variables de la même façon que n'importe lequel des types intégrés parce qu'il vous empêchera d'être en mesure d'accéder à l'un d'eux si vous en avez besoin-et il est déroutant pour d'autres qui sont habitués aux noms désignant un de ces éléments standard. Pour cette raison, vous devriez renommer votre variable list modifier quelque chose de différent pour éviter ce genre de problèmes.

Voici une version de travail de votre avec ces changements, j'ai aussi simplifié le if l'expression statement que vous avez eu vérifie si la clé est déjà dans le dictionnaire - Il y a même des façons implicites plus courtes de faire ce genre de chose, mais l'utilisation d'une déclaration conditionnelle est très bien pour l'instant.

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

Sortie:

d: {'AAA': ['111', '112'], 'AAC': ['123'], 'AAB': ['111']}
4
répondu martineau 2018-09-20 22:09:31

TypeError qui se passe parce que k est une liste, puisqu'elle est créée en utilisant une tranche d'une autre liste avec la ligne k = list[0:j]. Cela devrait probablement être quelque chose comme k = ' '.join(list[0:j]), donc vous avez une chaîne à la place.

En plus de cela, votre if l'énoncé est incorrect tel que noté par la réponse de Jesse, qui devrait lire if k not in d ou if not k in d (je préfère le dernier).

vous effacez aussi votre dictionnaire à chaque itération puisque vous avez d = {} à l'intérieur de votre for boucle.

notez que vous ne devez pas non plus utiliser list ou file comme noms variables, puisque vous masquerez les builtins.

Voici comment je pourrais reprendre ton code:

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

dict.setdefault() méthode ci-dessus remplace le if k not in d logique de votre code.

0
répondu Andrew Clark 2012-12-02 23:55:46
    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)
-2
répondu raton 2012-12-03 14:59:51