5 variants to invert dictionaries with non-unique values - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: General Coding Help (https://python-forum.io/forum-8.html) +--- Thread: 5 variants to invert dictionaries with non-unique values (/thread-29386.html) |
5 variants to invert dictionaries with non-unique values - Drakax1 - Aug-31-2020 Hi all, I was wondering if it was possible to rewrite the variants #1 #2 or #3 into a single line of code like variants #4 and #5? my_map = {'a': 3, 'c': 2, 'b': 2, 'e': 3, 'd': 1, 'f': 2} #output = {3: ['a', 'e'], 2: ['c', 'b', 'f'], 1: ['d']} #var1 inv_map = {} for k, v in my_map.items(): inv_map[v] = inv_map.get(v, []) + [k] print(inv_map) #var2 (The best/fastest overall?) inv_map2 = {} for k, v in my_map.items(): inv_map2.setdefault(v, set()).add(k) print(inv_map2) #var3 inv_map3 = {} for k, v in my_map.items(): inv_map3.setdefault(v, list()).append(k) print(inv_map3) #var4 print({v:[k for k in my_map.keys() if my_map[k] == v ] for k,v in my_map.items()}) #var5 print({v:[k for k in my_map if my_map[k] == v] for v in my_map.values()}) RE: 5 variants to invert dictionaries with non-unique values - DeaD_EyE - Aug-31-2020 Not a one-liner, but a code snippet, which is readable: from collections import defaultdict result = defaultdict(list) for key, value in my_map.items(): result[value].append(key) RE: 5 variants to invert dictionaries with non-unique values - snippsat - Aug-31-2020 (Aug-31-2020, 09:20 AM)Drakax1 Wrote: I was wondering if it was possible to rewrite the variants #1 #2 or #3 into a singlePossible,but not gone try it If have to think long about then then the readability in that line will be poor. I would probably write this like @DeaD_EyE,as i like defaultdict and in general stuff from collections module. Drakax1 Wrote:#var2 (The best/fastest overall?)That's and interpretation as best also be looked at as most pythonic/readable. Here a setup with timeit,if want to test speed. import timeit ver_1 = '''\ my_map = {'a': 3, 'c': 2, 'b': 2, 'e': 3, 'd': 1, 'f': 2} inv_map = {} for k, v in my_map.items(): inv_map[v] = inv_map.get(v, []) + [k]''' ver_2 = '''\ my_map = {'a': 3, 'c': 2, 'b': 2, 'e': 3, 'd': 1, 'f': 2} inv_map2 = {} for k, v in my_map.items(): inv_map2.setdefault(v, set()).add(k)''' ver_3 = '''\ from collections import defaultdict my_map = {'a': 3, 'c': 2, 'b': 2, 'e': 3, 'd': 1, 'f': 2} result = defaultdict(list) for key, value in my_map.items(): result[value].append(key)''' ver_4_5 = '''\ my_map = {'a': 3, 'c': 2, 'b': 2, 'e': 3, 'd': 1, 'f': 2} #{v:[k for k in my_map.keys() if my_map[k] == v ] for k,v in my_map.items()} {v:[k for k in my_map if my_map[k] == v] for v in my_map.values()}''' print(timeit.Timer(stmt=ver_2).timeit(number=10000000))So ver_1 and 2 is fast. So can get this this 10000000 run with average time down to 5-sec,but then i run PyPy Here run ver_1. # Python 3.8 G:\pypy3.6-v7.1.1 λ python test_map.py 19.0559965 # PyPy 3.6 ver 7.1 G:\pypy3.6-v7.1.1 λ pypy3 test_map.py 5.330786000000001 |