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

Учитывая такой словарь:

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

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

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

person Brian M. Hunt    schedule 27.01.2009    source источник


Ответы (30)


Python 3+:

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

Python 2:

inv_map = {v: k for k, v in my_map.iteritems()}
person SilentGhost    schedule 27.01.2009
comment
В последних версиях Python 2.7.x my_map.items() также работает - person valentin; 28.02.2017
comment
@valentin Да, этот работает, но он менее эффективен, поскольку генерирует список пар, а не итератор. - person Arya McCarthy; 02.06.2017
comment
Это будет работать, за исключением того, что не будет работать, если в значениях нет единства. В этом случае вы потеряете некоторые записи - person gabuzo; 23.10.2017
comment
Да, как деталь реализации. The order-preserving aspect of this new implementation is considered an implementation detail and should not be relied upon. Нет никакой гарантии, что так и будет, поэтому не пишите код, полагаясь на то, что Dict будет вести себя так же, как OrderedDict. - person Mattias; 26.08.2018
comment
@Mattias, это верно для Python 3.6. Для версии 3.7 сохранение порядка является официальным: mail.python. org / pipermail / python-dev / 2017-December / 151283.html. BDFL так сказал. - person interDist; 30.10.2018
comment
@interDist Это кажется очень плохой идеей - person endolith; 16.02.2021

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

dict((v, k) for k, v in my_map.iteritems())
person Community    schedule 27.01.2009
comment
Значения тоже должны быть хешируемыми. - person John La Rooy; 24.05.2012
comment
@ Buttons840: Если значения не уникальны, то в любом случае уникальная инверсия словаря не выполняется или, другими словами, инвертирование не имеет смысла. - person Wrzlprmft; 25.10.2014
comment
@ Buttons840 Для значения появится только последний ключ. Вероятно, нет никаких гарантий относительно порядка вывода iteritems(), поэтому можно предположить, что произвольный ключ будет назначен для неуникального значения таким образом, который, по-видимому, будет воспроизводиться при некоторых условиях, но не в целом. - person Evgeni Sergeev; 21.04.2015
comment
Обратите внимание, конечно, что в Python 3 больше нет метода iteritems(), и этот подход не будет работать; вместо этого используйте items(), как показано в принятом ответе. Кроме того, понимание словаря сделает это лучше, чем вызов dict. - person Mark Amery; 16.07.2016
comment
@Wrzlprmft Существует естественное определение инверсии в случае неуникальных значений. Каждое значение отображается на набор ключей, ведущих к нему. - person Leo; 25.10.2016

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

inv_map = {}
for k, v in my_map.iteritems():
    inv_map[v] = inv_map.get(v, []) + [k]
person Robert Rossney    schedule 27.01.2009
comment
... или просто inv_map.setdefault (v, []). append (k). Раньше я был фанатом defaultdict, но потом меня слишком много раз облажали и я пришел к выводу, что на самом деле явное лучше, чем неявное. - person alsuren; 10.11.2010
comment
Этот ответ неверен для нескольких карт, добавлять здесь бесполезно, потому что значение каждый раз сбрасывается в пустой список, следует использовать set_default - person Yaroslav Bulatov; 22.04.2016
comment
@YaroslavBulatov нет, показанный здесь код не нарушен - inv_map.get(v, []) возвращает уже добавленный список, если он есть, поэтому присвоение не сбрасывается до пустого списка. Но setdefault все равно будет красивее. - person Mark Amery; 16.07.2016
comment
Набор здесь имел бы больше смысла. Ключи (вероятно) хешируемые, и нет никакого порядка. inv_map.setdefault(v, set()).add(k). - person Artyer; 11.08.2017
comment
В python3 используйте my_map.items() вместо my_map.iteritems(). - person apitsch; 15.04.2019
comment
Вы можете избежать setdefault, используя defaultdict: inv_map = collections.defaultdict(set), а затем просто inv_map[v].add(k) - person Conchylicultor; 30.01.2020
comment
Разве это не вычисление выражения [] и создание пустого списка на каждой итерации? - person Juan C. Roldán; 18.03.2021

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

def inverse_mapping(f):
    return f.__class__(map(reversed, f.items()))
person fs.    schedule 05.11.2009
comment
Это может быть умно, но это не работает, когда несколько ключей имеют одинаковое значение в исходном словаре. - person Rafael_Espericueta; 05.06.2018
comment
@Rafael_Espericueta Это верно для любого возможного ответа на этот вопрос, поскольку карта с повторяющимися значениями не обратима. - person Mark Amery; 15.07.2019
comment
@Mark_Amery Это может быть в некотором смысле обратимым. Например: D = {1: [1, 2], 2: [2, 3], 3: [1]}, Dinv = {1: [1, 3], 2: [1, 2], 3: [2]}. D - это словарь, например, {parent: children}, а Dinv - словарь {child: parent}. - person Rafael_Espericueta; 22.07.2019
comment
Я не думаю, что это необходимо делать f.__class__, потому что вы уже сделали предположение, что это словарь. Я бы так сделал: dict(map(reversed, f.items())) - person bkbilly; 05.07.2020
comment
@bkbilly не было сделано предположений, у нас есть диктант - только у нас есть items метод - person Mr_and_Mrs_D; 27.04.2021

Попробуй это:

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)

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

inv_map = {my_map[k] : k for k in my_map}
person sykora    schedule 27.01.2009
comment
Обратите внимание, что это работает только в том случае, если ключи уникальны (чего почти никогда не бывает, если вы хотите их инвертировать). - person gented; 22.06.2018
comment
Согласно пониманиям python.org/dev/peps/pep-0274 dict также доступны в версии 2.7+. - person Kawu; 27.10.2018

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

my_map = { 'a': 1, 'b':2 }
dict(map(reversed, my_map.items()))
person Brendan Maguire    schedule 26.02.2014
comment
Спасибо за публикацию. Я не уверен, что это предпочтительнее - цитируя Гвидо Ван Россума в PEP 279: filter и map должны умереть и быть включены в состав списков, а не увеличиваться в количестве вариантов. - person Brian M. Hunt; 26.02.2014
comment
Да, это справедливо, Брайан. Я просто добавлял это для разговора. Я могу представить, что способ понимания dict более читабелен для большинства. (И, вероятно, быстрее, я бы предположил) - person Brendan Maguire; 26.02.2014
comment
Может быть менее читаемым, чем другие, но у этого способа есть преимущество, заключающееся в возможности замены dict другими типами сопоставления, такими как collections.OrderedDict или collections.defaultdict - person Will S; 17.08.2017

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

person Acumenus    schedule 24.10.2012
comment
это также было бы хорошим местом для использования наборов вместо списков, т. е. revdict.setdefault(v, set()).add(k) - person mueslo; 22.12.2016
comment
Конечно, но именно поэтому это хорошая причина использовать set. Здесь применяется внутренний тип. Что, если я хочу найти все ключи, значения которых не равны 1 или 2? Тогда я могу просто сделать d.keys() - inv_d[1] - inv_d[2] (в Python 3) - person mueslo; 22.12.2016

Мы также можем перевернуть словарь с повторяющимися ключами, используя defaultdict:

from collections import Counter, defaultdict

def invert_dict(d):
    d_inv = defaultdict(list)
    for k, v in d.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().

person irudyak    schedule 26.12.2016
comment
Может быть полезно вернуть dict(d_inv), поскольку словарь имеет более широкую поддержку, чем менее стандартный defaultdict. Например, некоторые сериализаторы (такие как yaml.safe_dump) не будут сериализовать defaultdict, в то время как они будут сериализовать dict. - person Konstantin; 22.12.2020

Комбинация понимания списка и словаря. Может обрабатывать повторяющиеся ключи

{v:[i for i in d.keys() if d[i] == v ] for k,v in d.items()}
person SVJ    schedule 19.04.2018
comment
Как и stackoverflow.com/a/41861007/1709587, это решение проблемы O (n²), которое легко решается. в O (n) с парой дополнительных строк кода. - person Mark Amery; 15.07.2019

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

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

И вы хотите получить это в таком перевернутом виде:

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

Первое решение. Для инвертирования пар ключ-значение в словаре используйте подход for-цикла:

# Use this code to invert dictionaries that have non-unique values

inverted_dict = dict()
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]}
person Andy Fedoroff    schedule 10.01.2019
comment
dict зарезервирован и не должен использоваться для имен переменных - person crypdick; 19.08.2019
comment
забыл сказать нам, что такое my_map - person crypdick; 19.08.2019
comment
dictio()? Вы имели в виду dict()? - person Georgy; 01.10.2019

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

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

person NcAdams    schedule 28.09.2014
comment
Мне нравится эта идея, хотя было бы хорошо отметить, что она требует дополнительной памяти для улучшения вычислений. Более удачным средством может быть кеширование или ленивое вычисление зеркала. Также стоит отметить, что его можно было бы сделать более синтаксически привлекательным, например, представления словаря и пользовательские операторы. - person Brian M. Hunt; 28.09.2014
comment
@ BrianM.Hunt Это торгует памятью, но не сильно. Вы храните только два набора указателей на каждый объект. Если ваши объекты намного больше, чем отдельные целые числа, это не будет иметь большого значения. С другой стороны, если у вас огромная таблица крошечных объектов, вам, возможно, придется рассмотреть эти предложения ... - person NcAdams; 29.09.2014
comment
И я согласен, здесь нужно сделать еще больше - я мог бы преобразовать это в полностью функционирующий тип данных позже. - person NcAdams; 29.09.2014
comment
Эта реализация намного эффективнее, чем инвертирование всего словаря - ммм, почему? Я не вижу какого-либо правдоподобного способа, которым этот подход может дать существенный выигрыш в производительности; у вас все еще есть два словаря. Во всяком случае, я бы ожидал, что это будет медленнее, чем, скажем, инвертирование dict с пониманием, потому что, если вы инвертируете dict, Python может заранее достоверно знать, сколько сегментов выделить в базовом C структуры данных и создать обратную карту, даже не вызывая dictresize, но этот подход лишает Python такой возможности. - person Mark Amery; 16.07.2016

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

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() несколько раз.

person pcv    schedule 17.04.2010
comment
Это просто нечитабельно и хороший пример того, как не писать поддерживаемый код. Я не буду -1, потому что он все еще отвечает на вопрос, просто мое мнение. - person Russ Bradberry; 03.10.2012

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

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.

person Ersatz Kwisatz    schedule 25.01.2017
comment
Это решение довольно элегантно как однострочное и управляет случаем неуникальных значений. Однако он имеет сложность в O (n2), что означает, что он должен подходить для нескольких десятков элементов, но будет слишком медленным для практического использования, если у вас есть несколько сотен тысяч элементов в вашем исходном словаре. Решения, основанные на dict по умолчанию, намного быстрее, чем это. - person gabuzo; 24.10.2017
comment
Габузо совершенно прав. Эта версия (возможно) более четкая, чем некоторые, но она не подходит для больших данных. - person Ersatz Kwisatz; 25.10.2017

Я обнаружил, что эта версия более чем на 10% быстрее принятой версии словаря с 10000 ключами.

d = {i: str(i) for i in range(10000)}

new_d = dict(zip(d.values(), d.keys()))
person nauer    schedule 08.09.2020

Случай, когда значения словаря являются набором. Нравиться:

some_dict = {"1":{"a","b","c"},
        "2":{"d","e","f"},
        "3":{"g","h","i"}}

Обратное хотел бы:

some_dict = {vi: k  for k, v in some_dict.items() for vi in v}

Результат такой:

{'c': '1',
 'b': '1',
 'a': '1',
 'f': '2',
 'd': '2',
 'e': '2',
 'g': '3',
 'h': '3',
 'i': '3'}
person Mondaa    schedule 10.01.2021
comment
Это также работает, если значения словаря являются списком. Спасибо. - person catris25; 12.01.2021

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

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

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

invert = lambda mydict: dict( zip(mydict.values(), mydict.keys()) )
person RussellStewart    schedule 09.04.2013
comment
-1; все, что вы сделали, это взяли другие ответы со страницы и поместили их в лямбду. Кроме того, присвоение лямбда переменной является нарушением PEP 8. - person Mark Amery; 16.07.2016

Вот еще один способ сделать это.

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

inv_map= {}
for key in my_map.keys() :
    val = my_map[key]
    inv_map[val] = key
person Constantin Shimonenko    schedule 03.12.2020

Я знаю, что на этот вопрос уже есть много хороших ответов, но я хотел поделиться этим очень изящным решением, которое также заботится о повторяющихся значениях:

def dict_reverser(d):
    seen = set()
    return {v: k for k, v in d.items() if v not in seen or seen.add(v)}

Это основано на том факте, что set.add всегда возвращает None в Python.

person mss    schedule 14.01.2021

Много ответов, но не нашел ничего чистого, если мы говорим о словаре с неуникальными значениями.

Решение было бы:

from collections import defaultdict

inv_map = defaultdict(list) 
for k, v in my_map.items(): 
    inv_map[v].append(k)

Пример:

Если исходный dict my_map = {'c': 1, 'd': 5, 'a': 5, 'b': 10}

тогда выполнение приведенного выше кода даст:

{5: ['a', 'd'], 1: ['c'], 10: ['b']}
person Ani Menon    schedule 01.03.2021

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

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
person Alf    schedule 24.09.2014

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

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
person eyoeldefare    schedule 09.01.2016

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

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.

person cjay    schedule 06.03.2014
comment
Теоретически это должно быть быстрее, чем добавление в набор (или добавление в список) по одному - нет. Учитывая n элементов в исходном dict, ваш подход имеет O(n log n) временную сложность из-за необходимости сортировать элементы dict, тогда как наивный императивный подход имеет O(n) временную сложность. Насколько мне известно, ваш подход может быть быстрее до абсурдно больших dicts в практике, но, конечно, это не быстрее в теории. - person Mark Amery; 16.07.2016

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

inv_map={};
for i in my_map:
    inv_map[my_map[i]]=i    
print inv_map
person dhvlnyk    schedule 25.07.2014

Лямбда-решение для текущих версий Python 3.x:

d1 = dict(alice='apples', bob='bananas')
d2 = dict(map(lambda key: (d1[key], key), d1.keys()))
print(d2)

Результат:

{'apples': 'alice', 'bananas': 'bob'}

Это решение не проверяет дубликаты.

Некоторые замечания:

  • Лямбда-конструкция может обращаться к d1 из внешней области видимости, поэтому мы передаем только текущий ключ. Он возвращает кортеж.
  • Конструктор dict () принимает список кортежей. Он также принимает результат карты, поэтому мы можем пропустить преобразование в список.
  • Это решение не имеет явного for цикла. Он также избегает использования list comprehension для тех, кто плохо разбирается в математике ;-)
person mit    schedule 16.06.2020
comment
Я не смог найти это решение с помощью поиска Google или в других ответах или в дублирующих вопросах, поэтому я создал его. - person mit; 16.06.2020

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

inv_map = {my_map[x] : x for x in my_map}
person genghiscrade    schedule 26.04.2017
comment
Итерация пар ключ-значение одновременно через dict.items (или iteritems в Python 2) более эффективна, чем извлечение каждого значения отдельно при итерации ключей. - person jpp; 23.08.2019

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

person RVR    schedule 30.08.2017
comment
Итерация пар ключ-значение одновременно через dict.items (или iteritems в Python 2) более эффективна, чем извлечение каждого значения отдельно при итерации ключей. Кроме того, вы не добавили никаких объяснений к ответу, который дублирует другие. - person jpp; 25.08.2019

  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']}
person Shb8086    schedule 18.12.2017
comment
Как правило, ответы намного полезнее, если они включают объяснение того, для чего предназначен код, и почему это решает проблему, не вводя других. - person Tom Aranda; 18.12.2017
comment
Это очень приятно, но много необъяснимых решений (например, почему клавиши в нижнем регистре?) - person Liudvikas Akelis; 07.09.2018

Не совсем другое, просто немного переписанный рецепт из 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()

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

person thodnev    schedule 02.08.2016
comment
Создание результата как dict и последующее преобразование в желаемый класс в конце (вместо того, чтобы начинать с класса правильного типа), на мой взгляд, влечет за собой снижение производительности, которого можно полностью избежать. - person Mark Amery; 15.07.2019

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

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

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

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)
person mveith    schedule 10.01.2017
comment
Вы можете улучшить свои решения, используя defaultdict: он удалит все строки invDict [item] = invDict.get (item, []) - person gabuzo; 24.10.2017
comment
Ваш первый подход здесь преобразует {"foo": "bar"} в {'b': ['foo'], 'a': ['foo'], 'r': ['foo']} и вызывает исключение, если какое-либо значение в myDict не является повторяемым. Я не уверен, какое поведение вы пытались реализовать здесь, но то, что вы на самом деле реализовали, практически никому не понадобится. - person Mark Amery; 15.07.2019