Reputation: 1465
My input is:
files = {
'Input.txt': 'Randy',
'Code.py': 'Stan',
'Output.txt': 'Randy'
}
I want the output as:
{'Randy':['Input.txt','Output.txt'], 'Stan':['Code.py']}
Basicly it's the other direction of this switch key and values in a dict of lists
This is what I tried:
dictresult= {}
for key,value in files.items():
dictresult[key]=value
dictresult[value].append(key)
But it doesn't work. I get KeyError: 'Randy'
Upvotes: 4
Views: 3530
Reputation: 89617
Here are two ways how you can do it.
from collections import defaultdict
files = {"Input.txt": "Randy", "Code.py": "Stan", "Output.txt": "Randy"}
expected = {"Randy": ["Input.txt", "Output.txt"], "Stan": ["Code.py"]}
# 1st method. Using defaultdict
inverted_dict = defaultdict(list)
{inverted_dict[v].append(k) for k, v in files.items()}
assert inverted_dict == expected, "1st method"
# 2nd method. Using regular dict
inverted_dict = dict()
for key, value in files.items():
inverted_dict.setdefault(value, list()).append(key)
assert inverted_dict == expected, "2nd method"
print("PASSED!!!")
Upvotes: 0
Reputation: 408
There are a few problems with your code.
Let's review:
Firstly, you're getting key error because you're trying to append a value to key that doesn't exist. Why? because in you earlier statement you added a value to dict[key] and now you're trying to access/append dict[value].
dictresult[key]=value
You're assigning value to newly generated key, without any check. every new value will overwrite it.
dictresult[value].append(key)
You can achieve what you want by the following code:
d = {}
for key,value in files.items():
if value in d:
d[value].append(key)
else:
d[value] = [key]
print(d)
It will output:
{'Randy': ['Input.txt', 'Output.txt'], 'Stan': ['Code.py']}
How/why it works?
Let's review:
Upvotes: 4
Reputation: 3612
Here's simple approach where we iterate over keys
and values
of your original dict files
and create list for each value to append to it all keys corresponding to that value.
files = {
'Input.txt': 'Randy',
'Code.py': 'Stan',
'Output.txt': 'Randy'
}
dictresult= {}
for k, v in files.items():
if v not in dictresult:
dictresult[v] = [k]
else:
dictresult[v].append(k)
print(dictresult) # -> {'Randy': ['Output.txt', 'Input.txt'], 'Stan': ['Code.py']}
Upvotes: 5
Reputation: 16136
output = {}
for key, value in files.items():
output[value] = output.get(value, []) + [key]
print(output)
# {'Randy':['Input.txt','Output.txt'], 'Stan':['Code.py']}
Upvotes: 0
Reputation: 712
You can check if the value as a key exist in dictresult
Like
dictresult= {}
for key,value in files.items():
if not value in dictresult: dictresult [value]=[]
dictresult[value].append(key)
Upvotes: 0
Reputation: 6181
Try using defaultdict -
from collections import defaultdict
dictresult= defaultdict(list)
for key,value in files.items():
dictresult[value].append(key)
This will assume there is an empty list in every item in the dictionary so the append won't fail
Upvotes: 1