Luis
Luis

Reputation: 1465

How to switch values and keys with python dict?

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

Answers (6)

Vlad Bezden
Vlad Bezden

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

Nauman Naeem
Nauman Naeem

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)
    
  • 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.

Upvotes: 4

Filip Młynarski
Filip Młynarski

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

Anand Tripathi
Anand Tripathi

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

vaku
vaku

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

Tom Ron
Tom Ron

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

Related Questions