Python invertir / invertir un mapeo



Answers

Suponiendo que los valores en el dict son únicos:

dict((v, k) for k, v in my_map.iteritems())
Question

Dado un diccionario como ese:

my_map = { 'a': 1, 'b':2 }

¿Cómo se puede invertir este mapa para obtener:

inv_map = { 1: 'a', 2: 'b' }

NOTA my_map EDITOR: map cambiado a my_map para evitar conflictos con la función incorporada, map . Algunos comentarios pueden verse afectados a continuación.




Esto maneja valores no únicos y conserva gran parte del aspecto del caso único.

inv_map = {v:[k for k in my_map if my_map[k] == v] for v in my_map.itervalues()}

Para Python 3.x, reemplace itervalues por valores . No me puedo atribuir el mérito de esto ... fue sugerido por Icon Jack.




Otra forma más funcional:

my_map = { 'a': 1, 'b':2 }
dict(map(reversed, my_map.items()))



Además de las otras funciones sugeridas anteriormente, si te gustan las lambdas:

invert = lambda mydict: {v:k for k, v in mydict.items()}

O bien, podrías hacerlo de esta manera también:

invert = lambda mydict: dict( zip(mydict.values(), mydict.keys()) )



Para todos los tipos de diccionario, no importa si no tienen valores únicos para usar como claves, puede crear una lista de claves para cada valor

inv_map = {v: inv_map.get(v, []) + [k] for k,v in my_map.items()}



def inverse_mapping(f):
    return f.__class__(map(reversed, f.items()))



Solución funcional rápida para mapas no biyectivos (valores no únicos):

from itertools import imap, groupby

def fst(s):
    return s[0]

def snd(s):
    return s[1]

def inverseDict(d):
    """
    input d: a -> b
    output : b -> set(a)
    """
    return {
        v : set(imap(fst, kv_iter))
        for (v, kv_iter) in groupby(
            sorted(d.iteritems(),
                   key=snd),
            key=snd
        )
    }

En teoría, esto debería ser más rápido que agregar al conjunto (o agregar a la lista) uno por uno como en la solución imperativa .

Desafortunadamente los valores tienen que ser ordenables, la ordenación es requerida por groupby.




Prueba esto para python 2.7 / 3.x

inv_map={};
for i in my_map:
    inv_map[my_map[i]]=i    
print inv_map



def invertDictionary(d):
    myDict = {}
  for i in d:
     value = d.get(i)
     myDict.setdefault(value,[]).append(i)   
 return myDict
 print invertDictionary({'a':1, 'b':2, 'c':3 , 'd' : 1})

Esto proporcionará salida como: {1: ['a', 'd'], 2: ['b'], 3: ['c']}




La función es simétrica para los valores de la lista de tipos; Las tuplas se convierten en listas cuando se realiza reverse_dict (reverse_dict (dictionary))

def reverse_dict(dictionary):
    reverse_dict = {}
    for key, value in dictionary.iteritems():
        if not isinstance(value, (list, tuple)):
            value = [value]
        for val in value:
            reverse_dict[val] = reverse_dict.get(val, [])
            reverse_dict[val].append(key)
    for key, value in reverse_dict.iteritems():
        if len(value) == 1:
            reverse_dict[key] = value[0]
    return reverse_dict



Si los valores no son únicos, y eres un poco duro:

inv_map = dict(
    (v, [k for (k, xx) in filter(lambda (key, value): value == v, my_map.items())]) 
    for v in set(my_map.values())
)

Especialmente para un dict grande, tenga en cuenta que esta solución es mucho menos eficiente que la respuesta. Python invierte / invierte un mapeo porque repite varios items() varias veces.




Escribí esto con la ayuda del ciclo 'for' y el método '.get ()' y cambié el nombre 'map' del diccionario a 'map1' porque 'map' es una función.

def dict_invert(map1):
    inv_map = {} # new dictionary
    for key in map1.keys():
        inv_map[map1.get(key)] = key
    return inv_map



Lo haría de esa manera en python 2.

inv_map = {my_map[x] : x for x in my_map}





Related