First of all my opinion is that your version is quite close to the best one. But it is possible to use a single for cycle or write it in just one line by use of map() and list compression instead of nested for cycles:
from collections import defaultdict
direct = {"a": [1, 2, 3], "b": [3], "c": [2, 4, 5], "d": [6]}
def invert(d):
ret = defaultdict(set)
for key, values in d.items():
for value in values:
ret[value].add(key)
return ret
def invert_alt(d):
ret = defaultdict(set)
list(map(lambda h: ret[h[1]].add(h[0]), [(key, value) for key in d for value in d[key]]))
return ret
def invert_final(d):
ret = defaultdict(set)
for key, value in [(key, value) for key in d for value in d[key]]:
ret[value].add(key)
return ret
print(invert(direct))
print(invert_alt(direct))
print(invert_final(direct))
Is it clear that invert_alt() have too much issues to use it:
- You should use
list() trick just in Python3 because map() is a generator and not evaluated until the code access to generator element, you don't need it in Python2.
- This implementation uses
map's side effect to do its job and my position is to avoid any use of side effects to complete the core jobs.
- Is really hard to understand.
For invert_final() you pay a little bit in clearness to remove a nested indentation: maybe a good compromise. Due to Python's formatting if you remove nesting indentation that is always a good goal.
map(). But IMHO that is not really better and even a trick because in Python 3 map is a generator and executed just when you evaluate generator I.e. you should add something like[:]at the end ofmapcode. \$\endgroup\$