6

I am looking for ways to swap all the key-value pairs of a given dictionary.

So far I could think of one way for doing it:

Ex:

>>>a = { 0: 'a', 1 : 'b', 2 : 'c' }
>>> {value : key for key,value in a.items()}
{'a': 0, 'b': 1, 'c' : 2}

But for this I would have to use extra space for declaring another dictionary.
I would like to know the methods could I use to swap the key-value pair more space-efficiency.

Kshitij Saraogi
  • 6,821
  • 8
  • 41
  • 71

3 Answers3

3

But for this I would have to use extra space for declaring another dictionary.

Since a dictionary is essentially a lookup table, there is a concrete way it is layed out in memory; the keys are distributed efficiently and just point to values which—by themselves—have no special meaning. Thus, when you want to reverse the mapping, you can’t really use the existing structure; instead you will have to create new dictionary entries from scratch. The dictionary comprehension you have used in your question is a good and clear way to do that.

What you could do however is to reuse the dictionary you already have and add the new keys there (while removing the old ones):

for k in a:
    a[a[k]] = k
    del a[k]

This modifies the same dictionary, so it won’t have the (likely little) overhead of a new dictionary. Note that this assumes that all values are unique too so the mapping can be exactly reversed, and that the set of keys and values don’t share common values. Otherwise, you will run into dictionary size changed exceptions or missing values. You can avoid the former by creating a copy of the dictionary keys (although this means that you have a list to store now too):

for k in list(a):
    if a[k] != k:
        a[a[k]] = k
        del a[k]

A final note: It’s possible that modifying the dictionary multiple times like that might have some remapping side-effects though (to increase the hash table size etc.), but that’s possible implementation detail of CPython (and I’m not too sure about it).

poke
  • 369,085
  • 72
  • 557
  • 602
  • 1
    As written, won't this (1) give a dictionary-changed-size error, and (2) not work in some cases, e.g. `a = {1:1, 2:3, 3:2}`? – DSM Jul 13 '15 at 10:41
  • @DSM Yes, that may be possible although it worked for me with OP’s example. You might have to create a copy of the key list though. As for (2), yes, for that example it will break, but I am assuming a situation similar to OP’s example here where the set of keys and the set of values is distinct. – poke Jul 13 '15 at 10:44
0

Try this code. It deletes the item in the dictionary before reversing key and value.

for k, v in a.items():
  del a[k]
  a[v] = k
soumen
  • 66
  • 5
0

To avoid the overwrite special cases that @DSM points out in @poke's answer, I recommend always using a second dictionary. The performance is identical.

b = dict()
for k, v in a.items(): # a.iteritems() in python 2
    b[v] = k
    del a[k]
a = b
Mathias Andersen
  • 478
  • 1
  • 4
  • 9