Обратное/обратное отображение словаря

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

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

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

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

Ответ 1

Для Python 2.7.x

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

Для Python 3 +:

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

Ответ 2

Предполагая, что значения в dict уникальны:

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

Ответ 3

Если значения в my_map не уникальны:

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

Ответ 4

Чтобы сделать это, сохранив тип отображения (при условии, что это подкласс dict или dict):

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

Ответ 5

Попробуйте следующее:

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

(Обратите внимание, что документы Python в словарных представлениях явно гарантируют, что .keys() и .values() имеют свои элементы в том же порядке, что позволяет использовать вышеприведенный подход.)

В качестве альтернативы:

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

или с использованием python 3.0 dict

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

Ответ 6

Другой, более функциональный способ:

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

Ответ 7

Это распространяется на ответ Роберта, применимый к случаям, когда значения в dict не являются уникальными.

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

Реализация ограничена тем, что вы не можете использовать reversed дважды и получить оригинал обратно. Это не симметрично как таковое. Протестировано с Python 2.6. Здесь - это пример использования того, как я использую для печати результирующий дикт.

Если вы предпочитаете использовать set, а не list, и могут существовать неупорядоченные приложения, для которых это имеет смысл, вместо setdefault(v, []).append(k) используйте setdefault(v, set()).add(k).

Ответ 8

Мы также можем изменить словарь с дубликатами ключей, используя 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']}  

Смотрите здесь:

Этот метод проще и быстрее, чем эквивалентный метод с использованием dict.setdefault().

Ответ 9

Добавление моих двухцентов питонического пути:

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

Пример:

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}

Ответ 10

Сочетание списка и словаря. Может обрабатывать дубликаты ключей

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

Ответ 11

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

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

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

Ответ 12

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

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

Ответ 13

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

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

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

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

Ответ 14

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

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 столько, сколько хотите, и ваш инверсионный словарь всегда будет оставаться верным - это неверно, если вы просто перевернули весь словарь один раз.

Ответ 15

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

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

Для Python 3.x замените itervalues на values.

Ответ 16

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

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

Ответ 17

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

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

Ответ 18

Функция симметрична для значений списка типов; Кортежи прикрываются списками при выполнении reverse_dict (reverse_dict (dictionary))

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

Ответ 19

Так как словари требуют одного уникального ключа в словаре в отличие от значений, мы должны добавить измененные значения в список сортировки, который будет включен в новые конкретные ключи.

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

Ответ 20

Быстрое функциональное решение для небиективных отображений (значения не единственные):

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

Теоретически это должно быть быстрее, чем добавление к набору (или добавление к списку) один за другим, как в императивном решении.

К сожалению, значения должны быть сортируемыми, сортировка требуется groupby.

Ответ 21

Я бы сделал это в python 2.

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

Ответ 22

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

Ответ 23

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

Ответ 24

Обратный ваш словарь:

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

print(inversed_dict_["v1"])

Ответ 25

Согласно моему комментарию к вопросу. Я думаю, что самый простой и один вкладыш, который работает как для Python2, так и для Python 3, будет

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

Ответ 26

Не совсем другое, просто переписан рецепт из Cookbook. Он более оптимизирован, сохраняя метод setdefault, а не каждый раз получая его через экземпляр:

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)

Предназначен для запуска под CPython 3.x, для 2.x замените mapping.items() на mapping.iteritems()

На моей машине работает немного быстрее, чем другие примеры здесь

Ответ 27

Я написал это с помощью цикла "for" и метода ".get()", и я изменил имя "карта" словаря на "map1", потому что "map" - это функция.

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

Ответ 28

Если значения не уникальны И может быть хешем (одно измерение):

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)

И с рекурсией, если вам нужно копать глубже, то только одно измерение:

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)

Ответ 29

Для всех видов словаря, независимо от того, не имеют ли они уникальных значений для использования в качестве ключей, вы можете создать список ключей для каждого значения

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

Ответ 30

Это не лучшее решение, но оно работает. Допустим, словарь, который мы хотим изменить, это:

dictionary = {'a': 1, 'b': 2, 'c': 3}, затем:

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

Выходные данные reverse_dictionary должны быть {1: 'a', 2: 'b', 3: 'c'}