I am currently working on a beginner's task (in Python): "Invert a dictionary: keys become values and values become keys. Original values are lists which, when transformed into keys, must not repeat!"
Firstly, I must write that I have seen several (similar) questions, but none are applicable to my task.
Secondly, I have tried writing a solution using nested for and if loops - unsuccessfully.
Then, I have written this code, after applying an internet solution:
def invert(dict1):
invertedDict1 = dict()
invertedDict1 = {value: key for key in dict1 for value in dict1[key]}
#print(dict1)
print(invertedDict1)
dict1 = {1: [2, 3, 5],
2: [1, 4],
3: [1, 2],
}
invert(dict1)
Output:
{2: 3, 3: 1, 5: 1, 1: 3, 4: 2}
It should be:
{1:[2,3], 2:[1,3], 3:[1], 4:[2], 5:[1]}
Does someone know where did I make the mistake (or mistakes)?
P.S. I'm brand new to Python and come from a C/C background, so please understand my lack of Python-specific knowledge
Thanks!
CodePudding user response:
The problem with your construction is key duplicates, which are not allowed in a dict. Also you have nothing in your code about list (for values).
The way is to use a defaultdict
, with list
as values. If the key isn't present, it puts an empty list, then appends the key
in it.
from collections import defaultdict
def invert(dict1):
invertedDict1 = defaultdict(list)
for key, values in dict1.items():
for value in values:
invertedDict1[value].append(key)
return invertedDict1
dict1 = {1: [2, 3, 5], 2: [1, 4], 3: [1, 2], }
print(invert(dict1)) # {2: [1, 3], 3: [1], 5: [1], 1: [2, 3], 4: [2]}
CodePudding user response:
You can do this easily with defaultdict
:
from collections import defaultdict
d = defaultdict(list)
for k, v in dict1.items():
for x in v:
d[x].append(k)
print(d)
defaultdict(list, {2: [1, 3], 3: [1], 5: [1], 1: [2, 3], 4: [2]})
defaultdict(list)
will always return a list
when accessing a key: a new empty list []
if this the first time d[x]
is accessed, the existing list of values [k1, k2, ...]
associated to x
if d[x]
has been accessed before.
This way you can store all keys k
associated the x
in your lists
CodePudding user response:
azro's answer is excellent, but I just want to add an implementation without collections
if it helps. I'll use dict.setdefault(default=[])
to insert a new list if needed, otherwise get the existing list.
def invert(d):
inverted = {}
for k, v in d.items():
for x in v:
L = inverted.setdefault(x, [])
L.append(k)
return inverted
dict1 = {1: [2, 3, 5], 2: [1, 4], 3: [1, 2]}
print(invert(dict1)) # -> {2: [1, 3], 3: [1], 5: [1], 1: [2, 3], 4: [2]}
This line with setdefault
stands in for this:
if x not in inverted:
inverted[x] = []
L = inverted[x]