Переключить ключ и значение в словаре множеств - PullRequest
4 голосов
/ 26 марта 2020

У меня есть словарь что-то вроде:

d1 = {'0': {'a'}, '1': {'b'}, '2': {'c', 'd'}, '3': {'E','F','G'}}

, и я хочу получить такой результат

d2 = {'a': '0', 'b': '1', 'c': '2', 'd': '2', 'E': '3', 'F': '3', 'G': '3'}

, поэтому я попытался

d2 = dict ((v, k) for k, v in d1.items())

, но значение окружено set {}, так что это не сработало ... могу ли я это исправить?

Ответы [ 3 ]

6 голосов
/ 26 марта 2020

Вы можете использовать словарное понимание:

{v:k for k,vals in d1.items() for v in vals}
# {'a': '0', 'b': '1', 'c': '2', 'd': '2', 'E': '3', 'F': '3', 'G': '3'}

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

3 голосов
/ 26 марта 2020

Другое понимание слова:

>>> {v: k for k in d1 for v in d1[k]}
{'a': '0', 'b': '1', 'c': '2', 'd': '2', 'E': '3', 'F': '3', 'G': '3'}

Сравнение эталонов с yatu:

from timeit import repeat
setup = "d1 = {'0': {'a'}, '1': {'b'}, '2': {'c', 'd'}, '3': {'E','F','G'}}"
yatu = "{v:k for k,vals in d1.items() for v in vals}"
heap = "{v:k for k in d1 for v in d1[k]}"
for _ in range(3):
    print('yatu', min(repeat(yatu, setup)))
    print('heap', min(repeat(heap, setup)))
    print()

Результаты:

yatu 1.4274586000000227
heap 1.4059823000000051

yatu 1.4562267999999676
heap 1.3701727999999775

yatu 1.4313863999999512
heap 1.3878657000000203

Еще один эталонный тест с миллионами ключей / значений :

setup = "d1 = {k: {k+1, k+2} for k in range(0, 10**6, 3)}"
for _ in range(3):
    print('yatu', min(repeat(yatu, setup, number=10)))
    print('heap', min(repeat(heap, setup, number=10)))
    print()

yatu 1.071519999999964
heap 1.1391495000000305

yatu 1.0880677000000105
heap 1.1534022000000732

yatu 1.0944767999999385
heap 1.1526202000000012

1 голос
/ 26 марта 2020

Вот еще одно возможное решение данной проблемы:

def flatten_dictionary(dct):
    d = {}
    for k, st_values in dct.items():
        for v in st_values:
            d[v] = k

    return d


if __name__ == '__main__':
    d1 = {'0': {'a'}, '1': {'b'}, '2': {'c', 'd'}, '3': {'E', 'F', 'G'}}
    d2 = flatten_dictionary(d1)
    print(d2)
...