Invirtiendo un diccionario con valores de lista

Por lo tanto, tengo este índice como un dict.

index = {'Testfil2.txt': ['nisse', 'hue', 'abe', 'pind'], 'Testfil1.txt': ['hue', 'abe', 'tosse', 'svend']} 

Necesito invertir el índice para que sea un dictado con duplicados de valores fusionados en una clave con las 2 claves originales como valores, como este:

 inverse = {'nisse' : ['Testfil2.txt'], 'hue' : ['Testfil2.txt', 'Testfil1.txt'], 'abe' : ['Testfil2.txt', 'Testfil1.txt'], 'pind' : ['Testfil2.txt'], 'tosse' : ['Testfil1.txt'], 'svend' : ['Testfil1.txt'] 

Sí, escribí lo anterior a mano.

Mi libro de texto tiene esta función para invertir diccionarios:

 def invert_dict(d): inverse = dict() for key in d: val = d[key] if val not in inverse: inverse[val] = [key] else: inverse[val].append(key) return inverse 

Funciona bien para una clave simple: pares de valores

PERO, cuando bash esa función con un dict que tiene listas como valores, como mi index , aparece este mensaje de error:

 invert_dict(index) Traceback (most recent call last): File "", line 1, in  invert_dict(index) File "", line 5, in invert_dict if val not in inverse: TypeError: unhashable type: 'list' 

He buscado durante una hora buscando una solución, el libro no sirve de nada y sospecho que puedo usar las tuplas de alguna manera, pero no estoy seguro de cómo. ¿Alguna ayuda?

He probado y quiere usar val not in inverse pero no se puede verificar si una “lista está en un dict”. ( val es una lista)

Para su código un simple cambio hará lo que quiera:

 def invert_dict(d): inverse = dict() for key in d: # Go through the list that is saved in the dict: for item in d[key]: # Check if in the inverted dict the key exists if item not in inverse: # If not create a new list inverse[item] = [key] else: inverse[item].append(key) return inverse 

Mi solución para revertir un diccionario, sin embargo, crea un nuevo diccionario new_dic :

 new_dic = {} for k,v in index.items(): for x in v: new_dic.setdefault(x,[]).append(k) 

Salida:

 {'tosse': ['Testfil1.txt'], 'nisse': ['Testfil2.txt'], 'svend': ['Testfil1.txt'], 'abe': ['Testfil1.txt', 'Testfil2.txt'], 'pind': ['Testfil2.txt'], 'hue': ['Testfil1.txt', 'Testfil2.txt']} 

No se pueden usar objetos de list como claves de diccionario, ya que deberían ser objetos de hashable. Puede recorrer sus elementos y utilizar el método dict.setdefault para crear el resultado esperado:

 >>> new = {} >>> >>> for k,value in index.items(): ... for v in value: ... new.setdefault(v,[]).append(k) ... >>> new {'hue': ['Testfil2.txt', 'Testfil1.txt'], 'svend': ['Testfil1.txt'], 'abe': ['Testfil2.txt', 'Testfil1.txt'], 'tosse': ['Testfil1.txt'], 'pind': ['Testfil2.txt'], 'nisse': ['Testfil2.txt']} 

y si está tratando con conjuntos de datos más grandes por negarse a llamar creando una lista vacía en cada método de setdefault() , puede usar collections.defaultdict() que llamará a la función faltante justo cuando encuentre una nueva clave.

 from collections import defaultdict new = defaultdict(list) for k,value in index.items(): for v in value: new[v].append(k) >>> new defaultdict(, {'hue': ['Testfil2.txt', 'Testfil1.txt'], 'svend': ['Testfil1.txt'], 'abe': ['Testfil2.txt', 'Testfil1.txt'], 'tosse': ['Testfil1.txt'], 'pind': ['Testfil2.txt'], 'nisse': ['Testfil2.txt']})