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 ofmap
code. – Michele d'Amico Nov 14 '15 at 21:42