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']})