python - Python invierte / invierte un mapeo




15 Answers

Para Python 2.7.x

inv_map = {v: k for k, v in my_map.iteritems()}

Para Python 3+:

inv_map = {v: k for k, v in my_map.items()}

Dado un diccionario como este:

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: el map cambió a my_map para evitar conflictos con la función incorporada, map . Algunos comentarios pueden verse afectados a continuación.




Si los valores en my_map no son únicos:

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



Prueba esto:

inv_map = dict(zip(my_map.values(), my_map.keys()))

(Tenga en cuenta que los documentos de Python en las vistas del diccionario garantizan explícitamente que .keys() y .values() tienen sus elementos en el mismo orden, lo que permite que el enfoque anterior funcione).

Alternativamente:

inv_map = dict((my_map[k], k) for k in my_map)

o usando dictaduras de Python 3.0

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



Esto expande la respuesta Python invierte / invierte una asignación , aplicándose a cuando los valores en el dict no son únicos.

class ReversibleDict(dict):

    def reversed(self):
        """
        Return a reversed dict, with common values in the original dict
        grouped into a list in the returned dict.

        Example:
        >>> d = ReversibleDict({'a': 3, 'c': 2, 'b': 2, 'e': 3, 'd': 1, 'f': 2})
        >>> d.reversed()
        {1: ['d'], 2: ['c', 'b', 'f'], 3: ['a', 'e']}
        """

        revdict = {}
        for k, v in self.iteritems():
            revdict.setdefault(v, []).append(k)
        return revdict

La implementación está limitada en el sentido de que no se puede utilizar reversed dos veces y recuperar el original. No es simétrico como tal. Se prueba con Python 2.6. Here hay un caso de uso de cómo estoy usando para imprimir el dictado resultante.

Si prefiere usar un set que una list , y hay aplicaciones para las que esto tiene sentido, en lugar de setdefault(v, []).append(k) , use setdefault(v, set()).add(k) .




Combinación de lista y comprensión de diccionario. Puede manejar claves duplicadas

{v:[i for i in d.keys() if d[i] == v ] for k,v in d.items()}



También podemos revertir un diccionario con claves duplicadas usando defaultdict :

from collections import Counter, defaultdict

def invert_dict(d):
    d_inv = defaultdict(list)
    for k, v in c.items():
        d_inv[v].append(k)
    return d_inv

text = 'aaa bbb ccc ddd aaa bbb ccc aaa' 
c = Counter(text.split()) # Counter({'aaa': 3, 'bbb': 2, 'ccc': 2, 'ddd': 1})
dict(invert_dict(c)) # {1: ['ddd'], 2: ['bbb', 'ccc'], 3: ['aaa']}  

Ver here

Esta técnica es más simple y más rápida que una técnica equivalente utilizando dict.setdefault() .




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, reemplaza itervalues con valores . No puedo tomar crédito por esto ... fue sugerido por Icon Jack.




Usando zip

inv_map = dict(zip(my_map.values(), my_map.keys()))



Lo haría así en python 2.

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



  def reverse_dictionary(input_dict):
      out = {}
      for v in input_dict.values():  
          for value in v:
              if value not in out:
                  out[value.lower()] = []

      for i in input_dict:
          for j in out:
              if j in map (lambda x : x.lower(),input_dict[i]):
                  out[j].append(i.lower())
                  out[j].sort()
      return out

este código hace de esta manera:

r = reverse_dictionary({'Accurate': ['exact', 'precise'], 'exact': ['precise'], 'astute': ['Smart', 'clever'], 'smart': ['clever', 'bright', 'talented']})

print(r)

{'precise': ['accurate', 'exact'], 'clever': ['astute', 'smart'], 'talented': ['smart'], 'bright': ['smart'], 'exact': ['accurate'], 'smart': ['astute']}



Dado que los diccionarios requieren una clave única dentro del diccionario a diferencia de los valores, tenemos que agregar los valores invertidos en una lista de clasificación para incluirlos dentro de las nuevas claves específicas.

def r_maping(dictionary):
    List_z=[]
    Map= {}
    for z, x in dictionary.iteritems(): #iterate through the keys and values
        Map.setdefault(x,List_z).append(z) #Setdefault is the same as dict[key]=default."The method returns the key value available in the dictionary and if given key is not available then it will return provided default value. Afterward, we will append into the default list our new values for the specific key.
    return Map



Si los valores no son únicos Y puede ser un hash (una dimensión):

for k, v in myDict.items():
    if len(v) > 1:
        for item in v:
            invDict[item] = invDict.get(item, [])
            invDict[item].append(k)
    else:
        invDict[v] = invDict.get(v, [])
        invDict[v].append(k)

Y con una recursión si necesita profundizar más, solo una dimensión:

def digList(lst):
    temp = []
    for item in lst:
        if type(item) is list:
            temp.append(digList(item))
        else:
            temp.append(item)
    return set(temp)

for k, v in myDict.items():
    if type(v) is list:
        items = digList(v)
        for item in items:
            invDict[item] = invDict.get(item, [])
            invDict[item].append(k)
    else:
        invDict[v] = invDict.get(v, [])
        invDict[v].append(k)



Según mi comentario a la pregunta. Creo que el más sencillo y un trazador de líneas que funciona tanto para Python2 como para Python 3 será

dict(zip(inv_map.values(), inv_map.keys()))



Escribí esto con la ayuda del ciclo 'para' y el método '.get ()' y cambié el nombre 'mapa' del diccionario a 'mapa1' porque 'mapa' 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



Esta no es la mejor solución, pero funciona. Digamos que el diccionario que queremos invertir es:

dictionary = {'a': 1, 'b': 2, 'c': 3}, entonces:

dictionary = {'a': 1, 'b': 2, 'c': 3}
reverse_dictionary = {}
for index, val in enumerate(list(dictionary.values())):
    reverse_dictionary[val] = list(dictionary.keys())[index]

La salida de reverse_dictionary, debe ser {1: 'a', 2: 'b', 3: 'c'}




Related

python dictionary mapping inverse