1

I'm trying to take a dictionary of keys and values and then swap the corresponding keys and values around, from looking through previously posted questions I know you can swap keys/ values of a dictionary around using something such as:

newdict = dict((b,a) for a,b in D.items())

I am also aware that dictionaries are not ordered, so with a lengthy dictionary the each key/ value pair will not be in the same position in the new dictionary as the original dictionary.

So my question is, is there any way of swapping the first pair of items then appending to a list (so they are in order) then append to a new dictionary? Then repeat this process for the second pair of terms and so on? This may seem a stupid question but it is one that I don't understand, any help will be greatly appreciated as always. :)

For clarification here is what my current code does:

D = {1:2, 3:4, 5:6, 8:9, 20:11} #this is the input

{9: 8, 2: 1, 11: 20, 4: 3, 6: 5} #this is the output

I would ideally like the output to be:

{2:1, 4:3, 6:5, 9:8, 11:20}

As a point of reference my code is simply:

def invert():
    newdict = list((b,a) for a,b in D.items())

D = {1:2, 3:4, 5:6, 8:9, 20:11}

invert()
Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
George Burrows
  • 3,391
  • 9
  • 31
  • 31
  • 1
    I'm sorry I'm having trouble understanding exactly what you're trying to do. Can you give an illustration with example data? – Joe Dec 04 '11 at 19:32
  • @Joe I've edited the question to illustrate the desired output, essentially as the dictionary is not ordered, the items are being swapped, but the key/value pairs are in an arbitrary order instead of the order they appear in the original dictionary. – George Burrows Dec 04 '11 at 19:41
  • I think you are missing something in your understanding. Since dictionaries are not ordered, you should not do anything that depends on the said order. For example, adding items to a dictionary in a certain order, does not guarantee the same ordering within the dict object if you go to iterate over it. – Derek Litz Dec 04 '11 at 19:43
  • This question in a Python book says I should be able to swap the keys/ values and preserve the order by some method other than ordered dictionaries though. :S – George Burrows Dec 04 '11 at 19:51

5 Answers5

3

OrderedDict as part of the solution

As you mentioned, dict does not have any specific order, thus you would need to implement dict-like data structure that can be ordered.

Good solution here is OrderedDict. You can create sorted OrderedDict like that:

>>> D = {9: 8, 2: 1, 11: 20, 4: 3, 6: 5}
>>> import collections
>>> E = collections.OrderedDict((i, D[i]) for i in sorted(D))
>>> E
OrderedDict([(2, 1), (4, 3), (6, 5), (9, 8), (11, 20)])

Inverting dictionary using OrderedDict

Your whole solution may look like this:

>>> D = {9: 8, 2: 1, 11: 20, 4: 3, 6: 5}
>>> def invert(D):
    import collections
    return collections.OrderedDict((D[i], i) for i in sorted(D))

>>> invert(D)
OrderedDict([(1, 2), (3, 4), (5, 6), (8, 9), (20, 11)])

Does it work for you?

Support in Python older than 2.7

OrderedDict is available in Python 2.x line since version 2.7 and in Python 3.x line since 3.1, but it can be implemented easily in older versions. If you need it in older versions, see this question ("OrderedDict for older versions of Python") and answers.

Community
  • 1
  • 1
Tadeck
  • 132,510
  • 28
  • 152
  • 198
1

You really want to use OrderedDicts to achieve this. The input order of your dictionary is irrelevant to how it is store internally.

Manny D
  • 20,310
  • 2
  • 29
  • 31
  • 2
    NB: only in Python 2.7 onward – Joe Dec 04 '11 at 19:46
  • @Joe Thanks for clarifying. OrderedDicts were only introduced in 2.7. – Manny D Dec 04 '11 at 19:48
  • @Joe: You can still use the code that enables similar feature in older versions. See [OrderedDict for older versions of python](http://stackoverflow.com/questions/1617078/ordereddict-for-older-versions-of-python). – Tadeck Dec 05 '11 at 09:11
0

You can't guarantee that the sort order is maintained in any dictionary.

If you want a structure so you can iterate over the values in order, I would just recommend a list of tuples:

D = [(1,2), (3,4), (5,6), (8,9), (20,11)]

to invert it:

Di = [(x,y) for (y,x) in D]

and to get a dictionary that you can look things up in:

DictD = dict(D)
DictDi = dict(Di)
Joe
  • 46,419
  • 33
  • 155
  • 245
0

There are no built-in functions to reorder a dictionary. If for any reason you want an ordered dictionary, you should keep a helper list besides your dictionary. In the following code list order is used to keep the order of the items. Whenever you want to iterate over your dictionary, actually iterate over order and use its items to index the dictionary.

def invert():
    order = [b for a,b in D.items()]
    newdict = dict((b,a) for a,b in D.items())
    return order

D = {1:2, 3:4, 5:6, 8:9, 20:11}

order = invert()

#This will print out the values in the order you want:
for i in order:
    print(newdict[i])

That being said, I'm not even sure that (b,a) for a,b in D.items() returns the items in current dictionary order. So even in the invert function instead of:

newdict = dict((b,a) for a,b in D.items())

you might want to write:

#Think the initial order is saved in initial_order
newdict = dict((D[a],a) for a in initial_order)

Another way is to use a list structure that contains an (index,value) pairs. I wanted to explain this but @Joe already did.

Hossein
  • 4,097
  • 2
  • 24
  • 46
0

Thing that you are trying to do is impossible since map is not arranged:

I would ideally like the output to be: {2:1, 4:3, 6:5, 9:8, 11:20}

e.g. if you create map with {2:1, 4:3, 6:5, 9:8, 11:20} and print it out you will see that ordering will be lost.

>>> {2:1, 4:3, 6:5, 9:8, 11:20}
{9: 8, 2: 1, 11: 20, 4: 3, 6: 5}  
>>> 
Mikael Lepistö
  • 18,909
  • 3
  • 68
  • 70