George Burrows
George Burrows

Reputation: 3501

Swapping items in a dictionary and order

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()

Upvotes: 1

Views: 5408

Answers (5)

Tadeck
Tadeck

Reputation: 137370

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.

Upvotes: 3

Hossein
Hossein

Reputation: 4137

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.

Upvotes: 0

Mikael Lepistö
Mikael Lepistö

Reputation: 19718

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}  
>>> 

Upvotes: 0

Manny D
Manny D

Reputation: 20724

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

Upvotes: 1

Joe
Joe

Reputation: 47619

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)

Upvotes: 0

Related Questions