4

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'

nucsit026
  • 652
  • 7
  • 16
Luis
  • 1,305
  • 5
  • 19
  • 46
  • Possible duplicate of [switching keys and values in a dictionary in python](https://stackoverflow.com/questions/8305518/switching-keys-and-values-in-a-dictionary-in-python) – juankysmith Apr 16 '19 at 10:57

6 Answers6

5

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']}
Filip Młynarski
  • 3,534
  • 1
  • 10
  • 22
4

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)
    
  • Then you're trying to append a new value to a string using a wrong 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:

  • The if condition checks if that key is already present in the dictionary. When iterated over a dictionary, it returns it's keys only, not key value pairs unlike dict.items()
  • If the key is there we simply append the current value to it.
  • In other case, where that key is not present, we add a new key to dictionary but we do it by casting it to a list, otherwise a string would be inserted as a value, not a list and you won't be able to append to it.
Nauman Naeem
  • 408
  • 3
  • 12
1

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

Tom Ron
  • 5,906
  • 3
  • 22
  • 38
0

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)
vaku
  • 697
  • 8
  • 17
0
output = {}
for key, value in files.items():
    output[value] = output.get(value, []) + [key]

print(output)
# {'Randy':['Input.txt','Output.txt'], 'Stan':['Code.py']}
Anand Tripathi
  • 14,556
  • 1
  • 47
  • 52
0

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!!!")
Vlad Bezden
  • 83,883
  • 25
  • 248
  • 179