77

Say I have a dictionary like so:

my_dict = {2:3, 5:6, 8:9}

Is there a way that I can switch the keys and values to get:

{3:2, 6:5, 9:8}
selplacei
  • 124
  • 1
  • 10
me45
  • 1,059
  • 3
  • 14
  • 16

10 Answers10

125

For Python 3:

my_dict2 = {y: x for x, y in my_dict.items()}

For Python 2, you can use

my_dict2 = dict((y, x) for x, y in my_dict.iteritems())
Nico Schlömer
  • 53,797
  • 27
  • 201
  • 249
GWW
  • 43,129
  • 11
  • 115
  • 108
  • 8
    `.iteritems()` is not valid on Python 3.x... – JBernardo Nov 29 '11 at 03:47
  • @JBernardo: Fixed thanks I forgot about that – GWW Nov 29 '11 at 03:48
  • 3
    another correction - doing the dictionary comprehension you suggest `{(y, x) for x, y in dic_cols_w.items()}` returns a set, not a dictionary. You would still need to wrap this in a `dict(...)` to get a dictionary – tsando Apr 05 '17 at 13:06
  • 4
    @tsando: I think you have read my answer incorrectly. I have `{y:x ...` – GWW Apr 05 '17 at 22:34
  • How would you do this if the values were a list of items and each item in the list should be a key? – Woody Pride Feb 06 '19 at 14:49
  • I am not sure I understand. Perhaps ask a new question or look for another answer? – GWW Feb 06 '19 at 21:48
  • In Python 3.6, it (2nd solution) still gives an error: `AttributeError: 'dict' object has no attribute 'iteritems'`. Any workaround? Thank you in advance! – Milan Feb 09 '22 at 14:54
  • 1
    For the future readers: for Python 3.x, use `item()` instead of `iteritems()` i.e. `my_dict2 = {y:x for x,y in my_dict.items()}`. Source: https://stackoverflow.com/a/483833/10358768 – Milan Feb 09 '22 at 14:57
14
my_dict = { my_dict[k]:k for k in my_dict}
Ingo Karkat
  • 167,457
  • 16
  • 250
  • 324
VladEg
  • 141
  • 1
  • 2
9

Try this:

my_dict = {2:3, 5:6, 8:9}

new_dict = {}
for k, v in my_dict.items():
    new_dict[v] = k
Óscar López
  • 232,561
  • 37
  • 312
  • 386
7

Use this code (trivially modified) from the accepted answer at Python reverse / invert a mapping:

dict((v,k) for k, v in my_dict.iteritems())

Note that this assumes that the values in the original dictionary are unique. Otherwise you'd end up with duplicate keys in the resulting dictionary, and that is not allowed.

And, as @wim points out, it also assumes the values are hashable. See the Python glossary if you're not sure what is and isn't hashable.

Community
  • 1
  • 1
Trott
  • 66,479
  • 23
  • 173
  • 212
6

maybe:

flipped_dict = dict(zip(my_dict.values(), my_dict.keys()))

aaron
  • 1,068
  • 12
  • 14
  • 2
    this is probably not safe as it relies on key and value ordering, although it happened to work for me. I like JBernardo/GWW's answer(s). – aaron Nov 29 '11 at 03:43
  • It's probably better to use `iterkeys` and `itervalues` – GWW Nov 29 '11 at 03:44
  • That's safe if the dict isn't changed during the operation. I liked because you did it without a comprehension. – JBernardo Nov 29 '11 at 03:51
3

First of all it is not guaranteed that this is possible, since the values of a dictionary can be unhashable.

In case these are not, we can use a functional approach with:

reversed_dict = dict(map(reversed, original_dict.items()))
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
2

Sometimes, the condition that the values are all unique will not hold, in which case, the answers above will destroy any duplicate values.

The following rolls the values that might be duplicates up into a list:

from itertools import count
dict([(a,[list(d.keys())[i] for i,j in zip(count(), d.values())if j==a in set(d.values())])

I'm sure there's a better (non-list-comp) method, but I had a problem with the earlier answers, so thought I'd provide my solution in case others have a similar use-case.

P.S. Don't expect the dict to remain neatly arranged after any changes to the original! This method is a one-time use only on a static dict - you have been warned!

Thomas Kimber
  • 10,601
  • 3
  • 25
  • 42
2

If the values are not unique this will collide the key space in conversion. Best is to keep the keys in list when switching places

below handles this -

RvsD = dict()
for k,v in MyDict.iteritems():
    RsvD.setdefault(v, []).append(k)
mungayree
  • 313
  • 1
  • 12
1

You can do it like this:

Function:

def inverse_dict(my_dict):
    updated_dict = {}
  
    for i in my_dict:
        updated_dict[my_dict[i]] = [i]

    return updated_dict

Main():

def main():
    year = {'day': 15, 'month': 3, 'year': 2019}
    print(inverse_dict(year))

if __name__ == "__main__":
    main()

Ouput:

{15: ['day'], 3: ['month'], 2019: ['year']}
Masthan
  • 727
  • 1
  • 8
  • 29
Alon Eilat
  • 53
  • 6
1

If values are not unique in the dictionary, then you can map keys to that value. Here an example of how to do it using defaultdict

from collections import defaultdict


def reverse_dict(data: dict) -> dict:
    rd = defaultdict(list)
    for k, v in data.items():
        rd[v].append(k)
    return rd


if __name__ == "__main__":
    from collections import Counter

    data = "aaa bbb ccc ddd aaa bbb ccc aaa"
    c = Counter(data.split())
    print(c)
    # Counter({'aaa': 3, 'bbb': 2, 'ccc': 2, 'ddd': 1})
    rd = reverse_dict(c)
    print(rd)
    # defaultdict(<class 'list'>, {3: ['aaa'], 2: ['bbb', 'ccc'], 1: ['ddd']})
Vlad Bezden
  • 83,883
  • 25
  • 248
  • 179