Python: TypeError: tipo inestable: ‘list’

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: unhashable type: 'list' . Sé que las claves de un diccionario no pueden ser listas, pero estoy intentando convertir mi valor en una lista, no en la clave. Me pregunto si cometí un error en alguna parte.

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 , necesitará 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 with open('filename.txt', 'rU') as f: (o incluso with open('filename.txt', 'r') as f: y debería funcionar bien.

Estás tratando de 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: 

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 claves de 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 "", line 1, in  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 "", line 1, in  TypeError: unhashable type: 'list' >>> hash(tuple([1, 2, 3, [4, 5,], 6, 7])) Traceback (most recent call last): File "", line 1, in  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.

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. Por otra parte, 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 variable de variable para evitar problemas como ese.

Aquí hay una versión de trabajo con estos cambios, también simplifiqué la expresión 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 statement 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']} 

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 statement if es incorrecta, como lo señala la respuesta de Jesse, que debería leer 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 el if k not in d lógica if k not in d de su código.

  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)