Pergunta

Dado um dicionário assim:

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

Como um invertido este mapa pode obter:

inv_map = { 1: 'a', 2: 'b' }
Foi útil?

Solução

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()}

Outras dicas

Assumindo que os valores no dict são únicos:

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

Se os valores em my_map não são exclusivos:

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

Para fazer isso, preservando o tipo do seu mapeamento (assumindo que é uma dict ou uma subclasse dict):

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

Tente isto:

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

(Note que os docs Python em vista dicionário explicitamente garantia de que .keys() e .values() têm os seus elementos na mesma ordem, que permite a abordagem acima para o trabalho.)

Como alternativa:

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

ou usando o Python 3.0 de compreensões dict

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

Outra, mais funcional, maneira:

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

Este expande a resposta https://stackoverflow.com/questions/ 483666 / pitão-reversa-inversa a um mapeamento / 485368 # 485368 , aplicando-se quando os valores na Dict não são ú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

A implementação é limitado em que você não pode usar reversed duas vezes e obter o original atrás. Não é simétrica como tal. É testado com o Python 2.6. Aqui está um caso de uso de como eu estou usando para imprimir o dict resultante.

Se você preferir usar um set que um list, e existem aplicações para o qual este faz sentido, em vez de setdefault(v, []).append(k), uso setdefault(v, set()).add(k).

Nós também pode reverter um dicionário com chaves 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']}  

aqui :

Esta técnica é mais simples e mais rápido do que uma técnica equivalente usando dict.setdefault().

A combinação de lista e compreensão dicionário. Pode lidar com chaves duplicadas

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

Como adicionar meus 2 centavos de maneira Python:

inv_map = dict(map(reversed, my_map.items()))

Exemplo:

In [7]: my_map
Out[7]: {1: 'one', 2: 'two', 3: 'three'}

In [8]: inv_map = dict(map(reversed, my_map.items()))

In [9]: inv_map
Out[9]: {'one': 1, 'three': 3, 'two': 2}

Se os valores não são únicos, e você está um pouco incondicional:

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 um grande dict, nota que esta solução é muito menos eficiente do que a resposta Python inversa / invertido um mapeamento porque loop sobre items() várias vezes.

Além das outras funções sugerido acima, se você gosta de lambdas:

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

Ou, você poderia fazê-lo desta forma também:

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

Eu acho que a melhor maneira de fazer isso é definir uma classe. Aqui é uma implementação de um "dicionário simétrica":

class SymDict:
    def __init__(self):
        self.aToB = {}
        self.bToA = {}

    def assocAB(self, a, b):
        # Stores and returns a tuple (a,b) of overwritten bindings
        currB = None
        if a in self.aToB: currB = self.bToA[a]
        currA = None
        if b in self.bToA: currA = self.aToB[b]

        self.aToB[a] = b
        self.bToA[b] = a
        return (currA, currB)

    def lookupA(self, a):
        if a in self.aToB:
            return self.aToB[a]
        return None

    def lookupB(self, b):
        if b in self.bToA:
            return self.bToA[b]
        return None

exclusão e de iteração métodos são bastante fáceis de implementar, se eles são necessários.

Esta implementação é muito mais eficiente do que invertendo um dicionário inteiro (o que parece ser a solução mais popular nesta página). Para não mencionar, você pode adicionar ou remover valores de seu SymDict tanto quanto você quer, e seu inverso do dicionário vai ficar sempre válido - isso não é verdade se você simplesmente inverter o dicionário inteiro uma vez

.

Usando zip

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

Este trata valores não-exclusivas e mantém muito do olhar do 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, substitua itervalues ?? com valores . Eu não posso levar o crédito por isso ... foi sugerido por Ícone Jack.

Tente isto para Python 2.7 / 3.x

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

Por exemplo, você tem o seguinte dicionário:

dict = {'a': 'fire', 'b': 'ice', 'c': 'fire', 'd': 'water'}

E você quer obtê-lo em tal uma forma invertida:

inverted_dict = {'fire': ['a', 'c'], 'ice': ['b'], 'water': ['d']}

Primeira Solução . Para inverter key-value pares em seu uso dicionário uma abordagem for-loop:

# Use this code to invert dictionaries that have non-unique values

inverted_dict = dictio()
for key, value in dict.items():
    inverted_dict.setdefault(value, list()).append(key)

Segunda Solução . Use um dicionário compreensão abordagem para a inversão:

# Use this code to invert dictionaries that have unique values

inverted_dict = {value: key for key, value in dict.items()}

terceira solução . Use reverter a inversão abordagem:

# Use this code to invert dictionaries that have lists of values

dict = {value: key for key in inverted_dict for value in my_map[key]}

A função é simétrica para valores de lista de tipos; Tuplos são convertidos em listas ao realizar Dict reversa (Dict reversa (dicionário))

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

Desde dicionários exigem uma chave única dentro do dicionário ao contrário de valores, temos que acrescentar os valores invertidos em uma lista de espécie para ser incluído dentro das novas teclas 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

Gostaria de fazê-lo dessa maneira em python 2.

inv_map = {my_map[x] : x for x in my_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})

Isto irá proporcionar uma saída como: {1: [ 'a', 'd'], 2: [ 'b'], 3: [ 'c']}

  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 fazer assim:

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

solução rápida funcional para mapas sem bijective (valores não originais):

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

Em teoria, isso deve ser mais rápido do que adicionar ao conjunto (ou acrescentar à lista), um por um, como na solução imperativo .

Infelizmente os valores têm de ser classificáveis, a classificação é exigida por groupby.

Não é algo completamente diferente, apenas uma receita pouco reescrito do Cookbook. É de Futhermore otimizado retendo método setdefault, em vez de cada vez que consegui-lo através do exemplo:

def inverse(mapping):
    '''
    A function to inverse mapping, collecting keys with simillar values
    in list. Careful to retain original type and to be fast.
    >> d = dict(a=1, b=2, c=1, d=3, e=2, f=1, g=5, h=2)
    >> inverse(d)
    {1: ['f', 'c', 'a'], 2: ['h', 'b', 'e'], 3: ['d'], 5: ['g']}
    '''
    res = {}
    setdef = res.setdefault
    for key, value in mapping.items():
        setdef(value, []).append(key)
    return res if mapping.__class__==dict else mapping.__class__(res)

Concebido para ser executado sob CPython 3.x, para 2.x substituir mapping.items() com mapping.iteritems()

Na minha máquina funciona um pouco mais rápido do que outros exemplos aqui

Se os valores não são exclusivos e pode ser um hash (uma dimensão):

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)

E com uma recursão se você precisa cavar mais fundo, em seguida, apenas uma dimensão:

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)

Inverse seu dicionário:

dict_ = {"k0":"v0", "k1":"v1", "k2":"v1"}
inversed_dict_ = {val: key for key, val in dict_.items()}

print(inversed_dict_["v1"])

Eu escrevi isso com a ajuda de ciclo 'para' e o método '.get ()' e eu mudei o nome 'mapa' do dicionário para 'map1' porque 'map' é uma função.

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

Para todos os tipos de dicionário, não importa se eles não têm valores exclusivos para usar como chaves, você pode criar uma lista de chaves para cada valor

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

Esta não é a melhor solução, mas funciona. Digamos que o dicionário queremos reverter é:

dicionário = { 'a': 1, 'b': 2, 'c': 3}, em seguida:

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

A saída de reverse_dictionary, deve ser {1: 'a', 2: 'b', 3: 'c'}

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top