traduction - python unhashable type
Python: TypeError: tipo inestable: ''list'' (6)
Nota: Esta respuesta no responde explícitamente a la pregunta formulada. Las otras respuestas lo hacen. Dado que la pregunta es específica para un escenario y la excepción planteada es general , esta respuesta apunta al caso general.
Los valores de hash son solo números enteros que se usan para comparar las claves del diccionario durante una búsqueda de diccionario rápidamente.
Internamente, el método hash()
llama al método __hash__()
de un objeto que se establece de forma predeterminada para cualquier objeto.
Convertir una lista anidada en un conjunto
>>> 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''
Esto sucede debido a la lista dentro de una lista que es una lista que no se puede hash. Que se puede resolver convirtiendo las listas anidadas internas en una tupla ,
>>> set([1, 2, 3, 4, (5, 6, 7), 8, 9])
set([1, 2, 3, 4, 8, 9, (5, 6, 7)])
Alinear explícitamente una lista anidada
>>> 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 solución para evitar este error es reestructurar la lista para tener tuplas anidadas en lugar de listas.
Estoy tratando de tomar un archivo que se parece a esto
AAA x 111
AAB x 111
AAA x 112
AAC x 123
...
Y usa un diccionario para que la salida se vea así.
{AAA: [''111'', ''112''], AAB: [''111''], AAC: [123], ...}
Esto es lo que he intentado
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()
Sigo obteniendo un TypeError: tipo inestable: ''lista''. Sé que las claves en un diccionario no pueden ser listas, pero estoy tratando de convertir mi valor en una lista, no en la clave. Me pregunto si cometí un error en alguna parte.
Gracias a todos los que me ayudaron con mi última pregunta.
Como lo indican las otras respuestas, el error es debido a k = list[0:j]
, donde su clave se convierte en una lista. Una cosa que podrías intentar es volver a trabajar tu código para aprovechar la función de 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'']}
Tenga en cuenta que si está usando Python 3.x, tendrá que hacer un pequeño ajuste para que funcione correctamente. Si abre el archivo con rb
, deberá usar line = line.split(b''x'')
(lo que garantiza que esté dividiendo el byte con el tipo de cadena adecuado). También puede abrir el archivo usando with open(''filename.txt'', ''rU'') as f:
(o incluso with open(''filename.txt'', ''r'') as f:
y debería funcionar bien.
El TypeError
está ocurriendo porque k
es una lista, ya que se crea utilizando una porción de otra lista con la línea k = list[0:j]
. Probablemente debería ser algo como k = '' ''.join(list[0:j])
, así que tienes una cadena en su lugar.
Además de esto, su declaración if
es incorrecta, tal como lo señala la respuesta de Jesse, que debe leerse if k not in d
o if not k in d
(prefiero esta última).
También está borrando su diccionario en cada iteración ya que tiene d = {}
dentro de su bucle for
.
Tenga en cuenta que tampoco debe usar la list
o el file
como nombres de variables, ya que estará enmascarando los elementos integrados.
Aquí es cómo reescribiría su código:
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:]))
El método dict.setdefault()
anterior reemplaza la lógica if k not in d
lógica desde su código.
Estás intentando usar k
(que es una lista) como clave para d
. Las listas son mutables y no se pueden utilizar como claves de dictado.
Además, nunca está inicializando las listas en el diccionario, debido a esta línea:
if k not in d == False:
Que debería ser:
if k not in d == True:
Que en realidad debería ser:
if k not in d:
La razón por la que está obteniendo la unhashable type: ''list''
es porque k = list[0:j]
establece que k
sea un "segmento" de la lista, que lógicamente es otra lista, a menudo más corta. Lo que necesita es obtener solo el primer elemento de la lista, escrito como k = list[0]
. Lo mismo para v = list[j + 1:]
que debería ser v = list[2]
para el tercer elemento de la lista devuelto desde la llamada a readline.split(" ")
.
Noté varios otros problemas probables con el código, de los cuales mencionaré algunos. Uno grande es que no desea (re) inicializar d
con d = {}
para cada línea leída en el bucle. Otra es que generalmente no es una buena idea nombrar las variables de la misma forma que cualquiera de los tipos incorporados, ya que le impedirá acceder a uno de ellos si lo necesita, y confunde a otros que están acostumbrados a la nombres que designan uno de estos elementos estándar. Por esa razón, deberías cambiar el nombre de tu variable de la list
variables algo diferente para evitar problemas como ese.
Aquí hay una versión de trabajo con estos cambios, también simplifiqué la expresión de la sentencia if
que tenías, que comprueba si la clave ya está en el diccionario. Hay formas implícitas aún más cortas de hacer este tipo de cosas, pero usando una declaración condicional está bien por ahora.
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))
Salida:
d: {''AAA'': [''111'', ''112''], ''AAC'': [''123''], ''AAB'': [''111'']}
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)