Python обратный / инвертировать отображение - PullRequest
539 голосов
/ 27 января 2009

Приведенный словарь выглядит так:

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

Как можно инвертировать эту карту, чтобы получить:

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

ПРИМЕЧАНИЕ РЕДАКТОРА: map изменено на my_map, чтобы избежать конфликтов со встроенной функцией map. Некоторые комментарии могут быть затронуты ниже.

Ответы [ 31 ]

4 голосов
/ 18 апреля 2010

Если значения не являются уникальными, и вы немного хардкор:

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

Специально для большого слова, обратите внимание, что это решение гораздо менее эффективно, чем ответ Python реверс / инвертирование отображения , потому что оно повторяется items() несколько раз.

3 голосов
/ 25 января 2017

Это обрабатывает неуникальные значения и сохраняет большую часть внешнего вида уникального случая.

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

Для Python 3.x замените его значения на значения . Я не могу взять кредит на себя ... это было предложено Icon Jack.

3 голосов
/ 09 апреля 2013

В дополнение к другим функциям, предложенным выше, если вам нравятся лямбды:

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

Или вы тоже можете сделать это так:

invert = lambda mydict: dict( zip(mydict.values(), mydict.keys()) )
2 голосов
/ 28 сентября 2014

Я думаю, что лучший способ сделать это - определить класс. Вот реализация «симметричного словаря»:

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

Методы удаления и итерации достаточно просты для реализации, если они необходимы.

Эта реализация намного эффективнее, чем инвертирование всего словаря (который, похоже, является самым популярным решением на этой странице). Не говоря уже о том, что вы можете добавлять или удалять значения из вашего SymDict столько раз, сколько захотите, и ваш обратный словарь всегда останется действительным - это не так, если вы просто полностью измените словарь один раз.

2 голосов
/ 10 января 2019

Например, у вас есть следующий словарь:

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

И вы хотите получить его в такой перевернутой форме:

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

Первое решение . Для инвертирования пар ключ-значение в вашем словаре используйте подход 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)

Второе решение . Используйте словарь для понимания подход для инверсии:

# Use this code to invert dictionaries that have unique values

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

Третье решение . Используйте для обращения инверсии подход:

# 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]}
2 голосов
/ 12 сентября 2016

Использование zip

inv_map = dict(zip(my_map.values(), my_map.keys()))
1 голос
/ 18 декабря 2017
  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

этот код сделать так:

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 голос
/ 30 августа 2017
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})

Это обеспечит вывод в виде: {1: ['a', 'd'], 2: ['b'], 3: ['c']}

1 голос
/ 26 апреля 2017

Я бы сделал так в Python 2.

inv_map = {my_map[x] : x for x in my_map}
1 голос
/ 25 июля 2014

Попробуйте это для Python 2.7 / 3.x

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