web-dev-qa-db-de.com

Python invertieren/invertieren ein Mapping

Bei einem Wörterbuch wie folgt:

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

Wie kann man diese Karte invertieren, um zu erhalten:

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

EDITOR HINWEIS: map wurde in my_map geändert, um Konflikte mit der integrierten Funktion map zu vermeiden. Einige Kommentare können unten betroffen sein.

507
Brian M. Hunt

Für Python 2.7.x

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

Für Python 3+:

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

Angenommen, die Werte im Dikt sind eindeutig:

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

Wenn die Werte in my_map nicht eindeutig sind:

inv_map = {}
for k, v in my_map.iteritems():
    inv_map[v] = inv_map.get(v, [])
    inv_map[v].append(k)
109
Robert Rossney
def inverse_mapping(f):
    return f.__class__(map(reversed, f.items()))
38
fs.

Versuche dies:

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

(Beachten Sie, dass die Python-Dokumente zu Wörterbuchansichten explizit garantieren, dass .keys() und .values() ihre Elemente in derselben Reihenfolge haben, wodurch der oben beschriebene Ansatz funktioniert.)

Alternative:

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

oder mit Python 3.0s Diktierkenntnissen

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

Ein anderer, funktionaler Weg:

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

Dies erweitert die Antwort Python invertieren/invertieren ein Mapping und gilt, wenn die Werte im Diktat nicht eindeutig sind.

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

Die Implementierung ist insofern eingeschränkt, als Sie reversed nicht zweimal verwenden können und das Original zurückbekommen. Es ist als solches nicht symmetrisch. Es wird mit Python 2.6 getestet. Hier ist ein Anwendungsfall, wie ich das resultierende Diktat drucke.

Wenn Sie lieber eine set als eine list verwenden und es Anwendungen gibt, für die dies sinnvoll ist, verwenden Sie setdefault(v, []).append(k) anstelle von setdefault(v, set()).add(k).

7
A-B-B

Kombination von Listen- und Wörterbuchverständnis. Kann mit doppelten Schlüsseln umgehen

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

Hinzufügen meiner 2 Cent Pythonic-Methode:

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

Beispiel:

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}
5
Amit Kushwaha

Wir können ein Wörterbuch mit doppelten Schlüsseln auch mit defaultdict stornieren:

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

Siehe hier :

Diese Technik ist einfacher und schneller als eine äquivalente Technik, die dict.setdefault() verwendet.

4
irudyak

Wenn die Werte nicht eindeutig sind und Sie etwas hardcore sind:

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

Beachten Sie insbesondere für große Diktaturen, dass diese Lösung weitaus weniger effizient ist als die Antwort Python invertieren/invertieren eines Mappings , da es items() mehrfach durchläuft.

4
pcv

Zusätzlich zu den anderen oben genannten Funktionen, wenn Sie Lambdas mögen:

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

Oder Sie könnten es auch so machen:

invert = lambda mydict: dict( Zip(mydict.values(), mydict.keys()) )
3
RussellStewart

Dadurch werden nicht eindeutige Werte verarbeitet und das Aussehen des eindeutigen Falls bleibt weitgehend erhalten. 

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

Ersetzen Sie für Python 3.x itervalues ​​durch values ​​. Ich kann das nicht anerkennen ... wurde von Icon Jack vorgeschlagen. 

3
Ersatz Kwisatz

Verwenden von Zip

inv_map = dict(Zip(my_map.values(), my_map.keys()))
2
Kwaw Annor

Ich denke, der beste Weg, dies zu tun, ist die Definition einer Klasse. Hier ist eine Implementierung eines "symmetrischen Wörterbuchs":

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

Lösch- und Iterationsmethoden lassen sich leicht implementieren, wenn sie benötigt werden.

Diese Implementierung ist viel effizienter als das Invertieren eines gesamten Wörterbuchs (das auf dieser Seite die beliebteste Lösung zu sein scheint). Ganz zu schweigen davon, Sie können beliebig viele Werte zu Ihrem SymDict hinzufügen oder entfernen, und Ihr Invers-Wörterbuch bleibt immer gültig. Dies gilt nicht, wenn Sie das gesamte Wörterbuch einmal umkehren.

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

Dies liefert die Ausgabe als: {1: ['a', 'd'], 2: ['b'], 3: ['c']

1
RVR
  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

dieser Code gefällt mir:

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

Ich würde es in Python 2 so machen.

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

Versuchen Sie dies für Python 2.7/3.x

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

Inverse dein Wörterbuch:

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

print(inversed_dict_["v1"])
0
Miladiouss

Die Funktion ist für Werte der Typenliste symmetrisch. Tupel werden beim Durchführen eines umgekehrten Diktats in Listen umgewandelt (umgekehrtes Diktat (Wörterbuch)).

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
0
Alf

Wenn Werte nicht eindeutig sind UND möglicherweise ein Hash (eine Dimension) ist:

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)

Und mit einer Rekursion, wenn Sie tiefer graben müssen, als nur eine 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)
0
mveith

Wie in meinem Kommentar zur Frage. Ich denke, der einfachste und ein Liner, der sowohl für Python2 als auch für Python 3 funktioniert, wird sein 

dict(Zip(inv_map.values(), inv_map.keys()))
0
Seshadri VS

Beispielsweise haben Sie das folgende Wörterbuch:

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

Und Sie wollen es in einer solchen umgekehrten Form bekommen:

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

Erste Lösung . Um Schlüsselwert Paare in Ihrem Wörterbuch zu invertieren, verwenden Sie einen for-Loop-Ansatz:

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

Zweite Lösung . Verwenden Sie einen dictionary-Verstehensansatz für die Inversion:

# Use this code to invert dictionaries that have unique values

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

Dritte Lösung . Verwenden Sie die Umkehrung der 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]}
0
ARGeo

Da Wörterbücher im Gegensatz zu Werten einen eindeutigen Schlüssel innerhalb des Wörterbuchs benötigen, müssen wir die umgekehrten Werte in eine Sortierliste einfügen, die in die neuen spezifischen Schlüssel aufgenommen wird. 

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
0
EyoelD

Nicht etwas ganz anderes, nur ein bisschen ein neues Rezept von Cookbook. Es wird weiter optimiert, indem die setdefault-Methode beibehalten wird, anstatt jedes Mal die Instanz durchlaufen zu müssen:

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)

Entwickelt für die Ausführung unter CPython 3.x, für 2.x mapping.items() durch mapping.iteritems() ersetzen

Auf meinem Rechner läuft es etwas schneller als andere Beispiele hier

0
thodnev