Étant donné un dictionnaire comme celui-ci:
my_map = { 'a': 1, 'b':2 }
Comment peut-on inverser cette carte pour obtenir:
inv_map = { 1: 'a', 2: 'b' }
REMARQUE: map
a été remplacé par my_map
pour éviter les conflits avec la fonction intégrée, map
. Certains commentaires peuvent être affectés ci-dessous.
Pour Python 2.7.x
inv_map = {v: k for k, v in my_map.iteritems()}
Pour Python 3+:
inv_map = {v: k for k, v in my_map.items()}
En supposant que les valeurs du dict sont uniques:
dict((v, k) for k, v in my_map.iteritems())
Si les valeurs dans my_map
ne sont pas uniques:
inv_map = {}
for k, v in my_map.iteritems():
inv_map[v] = inv_map.get(v, [])
inv_map[v].append(k)
def inverse_mapping(f):
return f.__class__(map(reversed, f.items()))
Essaye ça:
inv_map = dict(Zip(my_map.values(), my_map.keys()))
(Notez que la documentation Python sur les vues de dictionnaire garantit explicitement que .keys()
et .values()
ont leurs éléments dans le même ordre, ce qui permet à l'approche ci-dessus de fonctionner.)
Alternativement:
inv_map = dict((my_map[k], k) for k in my_map)
ou en utilisant les interprétations dict de python 3.0
inv_map = {my_map[k] : k for k in my_map}
Une autre manière, plus fonctionnelle:
my_map = { 'a': 1, 'b':2 }
dict(map(reversed, my_map.items()))
Cela étend la réponse Python inverser/inverser un mappage , s’appliquant à lorsque les valeurs du dict ne sont pas uniques.
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
L'implémentation est limitée en ce sens que vous ne pouvez pas utiliser reversed
deux fois et récupérer l'original. Ce n'est pas symétrique en tant que tel. Il est testé avec Python 2.6. Ici est un cas d'utilisation de la façon dont j'utilise pour imprimer le dict résultant.
Si vous préférez utiliser une set
qu'une list
et qu'il existe des applications pour lesquelles cela a du sens, au lieu de setdefault(v, []).append(k)
, utilisez setdefault(v, set()).add(k)
.
Combinaison de la liste et de la compréhension du dictionnaire. Peut gérer les clés en double
{v:[i for i in d.keys() if d[i] == v ] for k,v in d.items()}
Ajout de mes 2 centimes de façon Pythonic:
inv_map = dict(map(reversed, my_map.items()))
Exemple:
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}
Nous pouvons également inverser un dictionnaire avec des clés dupliquées en utilisant 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']}
Voir ici :
Cette technique est plus simple et plus rapide qu’une technique équivalente utilisant
dict.setdefault()
.
Si les valeurs ne sont pas uniques et que vous êtes un peu hardcore:
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())
)
Notez que cette solution est beaucoup moins efficace que la réponse Python inverse/inverse un mappage , car il effectue une boucle sur items()
plusieurs fois.
En plus des autres fonctions suggérées ci-dessus, si vous aimez lambdas:
invert = lambda mydict: {v:k for k, v in mydict.items()}
Ou, vous pouvez le faire aussi:
invert = lambda mydict: dict( Zip(mydict.values(), mydict.keys()) )
Cela gère les valeurs non uniques et conserve une grande partie de l'aspect du cas unique.
inv_map = {v:[k for k in my_map if my_map[k] == v] for v in my_map.itervalues()}
Pour Python 3.x, remplacez itervalues par values . Je ne peux pas prendre le crédit pour cela ... cela a été suggéré par Icon Jack.
Utiliser Zip
inv_map = dict(Zip(my_map.values(), my_map.keys()))
Je pense que la meilleure façon de faire est de définir une classe. Voici une implémentation d'un "dictionnaire symétrique":
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
Les méthodes de suppression et d'itération sont assez faciles à mettre en œuvre si elles sont nécessaires.
Cette implémentation est bien plus efficace que l’inversion d’un dictionnaire entier (ce qui semble être la solution la plus populaire sur cette page). Sans oublier de mentionner que vous pouvez ajouter ou supprimer des valeurs de votre SymDict autant que vous le souhaitez et que votre dictionnaire inverse restera toujours valide. Ce n'est pas le cas si vous inversez simplement le dictionnaire entier une fois.
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})
Cela fournira une sortie sous forme de: {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
ce code fait comme ça:
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']}
Je le ferais de cette façon en python 2.
inv_map = {my_map[x] : x for x in my_map}
Essayez ceci pour Python 2.7/3.x
inv_map={};
for i in my_map:
inv_map[my_map[i]]=i
print inv_map
Inverse ton dictionnaire:
dict_ = {"k0":"v0", "k1":"v1", "k2":"v1"}
inversed_dict_ = {val: key for key, val in dict_.items()}
print(inversed_dict_["v1"])
La fonction est symétrique pour les valeurs de type list; Les tuples sont convertis en listes lors de l'exécution de dict inverse (dict inverse (dictionnaire))
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 les valeurs ne sont pas uniques ET peut être un hachage (une dimension):
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)
Et avec une récursion si vous avez besoin de creuser plus profondément, alors une seule dimension:
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)
Selon mon commentaire à la question. Je pense que le plus simple et un liner qui fonctionne à la fois pour Python2 et Python 3 sera
dict(Zip(inv_map.values(), inv_map.keys()))
Par exemple, vous avez le dictionnaire suivant:
dict = {'a': 'fire', 'b': 'ice', 'c': 'fire', 'd': 'water'}
Et vous voulez l'obtenir sous une forme aussi inversée:
inverted_dict = {'fire': ['a', 'c'], 'ice': ['b'], 'water': ['d']}
Première solution . Pour inverser valeur-clé , votre dictionnaire utilise une approche 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)
Deuxième solution . Utilisez une approche compréhension du dictionnaire pour l'inversion:
# Use this code to invert dictionaries that have unique values
inverted_dict = {value: key for key, value in dict.items()}
Troisième solution . Utilisez la méthode en inversant l’inversion:
# 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]}
Comme les dictionnaires nécessitent une clé unique dans le dictionnaire, contrairement aux valeurs, nous devons ajouter les valeurs inversées à une liste de tri pour les inclure dans les nouvelles clés spécifiques.
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
Pas quelque chose de complètement différent, juste une recette un peu réécrite de Cookbook. Il est en outre optimisé en conservant la méthode setdefault
, au lieu de la parcourir à chaque fois via l'instance:
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)
Conçu pour être exécuté sous CPython 3.x, pour 2.x, remplacez mapping.items()
par mapping.iteritems()
Sur ma machine tourne un peu plus vite, que d'autres exemples ici