Estoy intentando tomar un archivo que se parece a este
AAA x 111
AAB x 111
AAA x 112
AAC x 123
...
Y use un diccionario para que la salida se vea así
{AAA: ['111', '112'], AAB: ['111'], AAC: [123], ...}
Esto es lo que he probado
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 recibiendo un TypeError: unhashable type: 'list'
. 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.
fuente
Los valores hash son solo números enteros que se utilizan para comparar rápidamente las claves del diccionario durante una búsqueda de diccionario.
Internamente, el
hash()
método llama al__hash__()
método de un objeto que se establece de forma predeterminada para cualquier objeto.Convertir una lista anidada en un conjunto
Esto sucede debido a la lista dentro de una lista que es una lista que no se puede usar con hash. Que se puede resolver convirtiendo las listas anidadas internas en una tupla ,
Hash explícitamente una lista anidada
fuente
Estás intentando usar
k
(que es una lista) como clave parad
. Las listas son mutables y no se pueden utilizar como claves de diccionario.Además, nunca está inicializando las listas en el diccionario, debido a esta línea:
Que debería ser:
Que debería ser en realidad:
fuente
La razón por la que obtiene la
unhashable type: 'list'
excepción es porque losk = list[0:j]
conjuntosk
son un "segmento" de la lista, que es lógicamente otra lista, a menudo más corta. Lo que necesita es obtener solo el primer elemento de la lista, escrito asík = list[0]
. Lo mismo para lov = list[j + 1:]
cual debería ser solov = list[2]
para el tercer elemento de la lista devuelto por la llamada areadline.split(" ")
.Noté varios otros problemas probables con el código, de los cuales mencionaré algunos. Uno importante es que no desea (re) inicializar
d
cond = {}
cada línea leída en el bucle. Otra es que generalmente no es una buena idea nombrar las variables de la misma manera que cualquiera de los tipos integrados porque evitará que pueda acceder a uno de ellos si lo necesita, y es confuso para otros que están acostumbrados a nombres que designan uno de estos elementos estándar. Por esa razón, debe cambiar el nombre de su variablelist
variable por algo diferente para evitar problemas como ese.Aquí hay una versión funcional de su con estos cambios, también simplifiqué la
if
expresión de declaración que tenía que verifica 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 un condicional La declaración está bien por ahora.Salida:
fuente
El
TypeError
está sucediendo porquek
es una lista, ya que se crea utilizando un trozo de otra lista con la líneak = list[0:j]
. Esto probablemente debería ser algo comok = ' '.join(list[0:j])
, por lo que tiene una cadena en su lugar.Además de esto, su
if
declaración es incorrecta como lo indica la respuesta de Jesse, que debe leerif k not in d
oif not k in d
(prefiero la última).También está limpiando su diccionario en cada iteración, ya que tiene
d = {}
dentro de sufor
ciclo.Tenga en cuenta que tampoco debe usar
list
ofile
como nombres de variable, ya que enmascarará las incorporaciones.Así es como reescribiría su código:
El
dict.setdefault()
método anterior reemplaza laif k not in d
lógica de su código.fuente
not k in d
podría confundir a un novato como(not k) in d
, mientras quek not in d
no tiene ambigüedadnot in
se indica como operador .!a.contains(b)
.not in
puede ser más pitónico, solo encuentro el concepto de operadores de dos palabras más confuso que usar un inverso en una expresión booleana.fuente