Dado um dicionário como este:
my_map = {'a': 1, 'b': 2}
Como se pode inverter este mapa para obter:
inv_map = {1: 'a', 2: 'b'}
python
dictionary
mapping
reverse
Brian M. Hunt
fonte
fonte
my_map.items()
, também funcionaThe order-preserving aspect of this new implementation is considered an implementation detail and should not be relied upon
. Não há garantia de que continue assim, portanto, não escreva código contandoDict
com o mesmo comportamento deOrderedDict
.Supondo que os valores no dict sejam únicos:
fonte
iteritems()
será gerada, portanto, pode-se supor que uma chave arbitrária seja atribuída a um valor não exclusivo, de uma maneira que aparentemente seja reproduzível em algumas condições, mas não em geral.iteritems()
método e essa abordagem não funcionará; useitems()
-o como mostrado na resposta aceita. Além disso, uma compreensão do dicionário tornaria isso mais bonito do que chamardict
.Se os valores em
my_map
não forem exclusivos:fonte
inv_map.get(v, [])
retorna a lista já adicionada, se houver, para que a atribuição não seja redefinida para uma lista vazia.setdefault
ainda seria mais bonito, no entanto.inv_map.setdefault(v, set()).add(k)
.my_map.items()
vez demy_map.iteritems()
.Para fazer isso, preservando o tipo de seu mapeamento (supondo que seja uma
dict
ou umadict
subclasse):fonte
Tente o seguinte:
(Observe que os documentos do Python nas visualizações de dicionário garantem explicitamente isso
.keys()
e.values()
têm seus elementos na mesma ordem, o que permite que a abordagem acima funcione.)Alternativamente:
ou usando as compreensões de ditado do python 3.0
fonte
Outra maneira mais funcional:
fonte
filter
emap
deve morrer e ser incluído na compreensão da lista, e não aumentar mais variantes".dict
com outros tipos de mapeamento, comocollections.OrderedDict
oucollections.defaultdict
Isso se expande com a resposta de Robert , aplicada quando os valores no ditado não são únicos.
A implementação é limitada, pois você não pode usar
reversed
duas vezes e obter o original de volta. Não é simétrico como tal. É testado com o Python 2.6. Aqui está um caso de uso de como estou usando para imprimir o ditado resultante.Se você preferir usar a do
set
que alist
, e pode haver aplicativos não ordenados para os quais isso faz sentido, em vez desetdefault(v, []).append(k)
usarsetdefault(v, set()).add(k)
.fonte
revdict.setdefault(v, set()).add(k)
set
. É o tipo intrínseco que se aplica aqui. E se eu quiser encontrar todas as chaves onde os valores não estão1
ou2
? Então eu posso apenas fazerd.keys() - inv_d[1] - inv_d[2]
(em Python 3) #Também podemos reverter um dicionário com chaves duplicadas usando
defaultdict
:Veja aqui :
fonte
Por exemplo, você tem o seguinte dicionário:
E você quer obtê-lo de forma invertida:
Primeira solução . Para inverter pares de valores-chave em seu dicionário, use uma
for
abordagem -loop:Segunda solução . Use uma abordagem de compreensão de dicionário para inversão:
Terceira solução . Use a reversão da abordagem de inversão (depende da segunda solução):
fonte
dict
é reservado e não deve ser usado para nomes de variáveismy_map
édictio()
? Você quis dizerdict()
?Combinação de lista e compreensão de dicionário. Pode lidar com chaves duplicadas
fonte
Se os valores não forem únicos e você for um pouco incondicional:
Especialmente para um ditado grande, observe que essa solução é muito menos eficiente que a resposta Python inverte / inverte um mapeamento, porque ele faz um loop
items()
várias vezes.fonte
-1
porque ainda responde à pergunta, apenas a minha opinião.Além das outras funções sugeridas acima, se você gosta de lambdas:
Ou você também pode fazer o seguinte:
fonte
Eu acho que a melhor maneira de fazer isso é definir uma classe. Aqui está uma implementação de um "dicionário simétrico":
Os métodos de exclusão e iteração são fáceis de implementar, se necessários.
Essa implementação é muito mais eficiente do que inverter um dicionário inteiro (que parece ser a solução mais popular nesta página). Sem mencionar, você pode adicionar ou remover valores do seu SymDict o quanto quiser, e seu dicionário inverso sempre permanecerá válido - isso não é verdade se você simplesmente reverter o dicionário inteiro uma vez.
fonte
dictresize
, mas essa abordagem nega ao Python essa possibilidade.Isso lida com valores não exclusivos e mantém grande parte da aparência do caso exclusivo.
Para Python 3.x, substitua
itervalues
porvalues
.fonte
Função é simétrica para valores da lista de tipos; As tuplas são ocultas em listas ao executar reverse_dict (reverse_dict (dictionary))
fonte
Como os dicionários exigem uma chave exclusiva no dicionário, diferentemente dos valores, precisamos anexar os valores revertidos em uma lista de classificação a ser incluída nas novas chaves específicas.
fonte
Solução funcional rápida para mapas não-bijetivos (valores não exclusivos):
Em teoria, isso deve ser mais rápido do que adicionar ao conjunto (ou anexar à lista) um por um, como na solução imperativa .
Infelizmente, os valores precisam ser classificados, a classificação é exigida por groupby.
fonte
n
elementos no ditado original, sua abordagem temO(n log n)
complexidade de tempo devido à necessidade de classificar os itens do ditado, enquanto a abordagem imperativa ingênua temO(n)
complexidade de tempo. Pelo que sei, sua abordagem pode ser mais rápida, até absurdamente grandedict
na prática , mas certamente não é mais rápida na teoria.Tente isso para python 2.7 / 3.x
fonte
Eu faria assim em python 2.
fonte
dict.items
(ouiteritems
no Python 2) é mais eficiente do que extrair cada valor separadamente enquanto itera as chaves.Isso fornecerá a saída como: {1: ['a', 'd'], 2: ['b'], 3: ['c']}
fonte
dict.items
(ouiteritems
no Python 2) é mais eficiente do que extrair cada valor separadamente enquanto itera as chaves. Além disso, você não adicionou nenhuma explicação a uma resposta que duplica outras.este código faz assim:
fonte
Não é algo completamente diferente, apenas uma receita reescrita do Cookbook. Além disso, é otimizado pelo
setdefault
método de retenção , em vez de obtê-lo através da instância:Projetado para ser executado no CPython 3.x, para 2.x substitua
mapping.items()
pormapping.iteritems()
Na minha máquina roda um pouco mais rápido do que outros exemplos aqui
fonte
dict
e depois converter para a classe desejada no final (em vez de começar com uma classe do tipo certo) me parece que incorre em um impacto de desempenho totalmente evitável aqui.Escrevi isso com a ajuda do ciclo 'for' e do método '.get ()' e mudei o nome 'map' do dicionário para 'map1' porque 'map' é uma função.
fonte
Se os valores não forem únicos E puder ser um hash (uma dimensão):
E com uma recursão, se você precisar ir mais fundo, apenas uma dimensão:
fonte
{"foo": "bar"}
para{'b': ['foo'], 'a': ['foo'], 'r': ['foo']}
e levanta uma exceção se qualquer valormyDict
não é um iterável. Não tenho certeza de qual comportamento você estava tentando implementar aqui, mas o que você realmente implementou é algo que praticamente ninguém vai querer.