-2

I wrote a program and then regretted not making certain objects earlier on OrderedDicts instead of dicts. So to fix this after the fact, the one dictionary was converted into an OrderedDict, but I needed to convert the second dictionary also to become an OrderedDict, but with its keys in the same order as the first.

A dict often displays in a way that looks deceivingly ordered, I almost made a mistake. There's a few questions about this apparent ordering here and here. Anyway, however ordered it may look to the eye, one needs to remember:

{'a':5,'b':7, 'c':3, 'd':9} == {'d':9,'b':7,'a':5, 'c':3}
>> True

So if there are two Python dictionaries:

a = {'a':5, 'b':7, 'c':3, 'd':9} b = {'c':2, 'b':1, 'd':17, 'a':8}

I can fix the order of a like this:

c = OrderedDict(a)
print (c)
>> OrderedDict([('a', 5), ('b', 7), ('c', 3), ('d', 9)])

How do you impose order on dictionary b, convert it into an OrderedDict with its keys in the same order as a?

In my exact use case, both dictionaries have the same keys, but I would be interested to know how you can do this in general, say instead your two dictionaries were:

a = {'a':5, 'b':7, 'c':3, 'd':9}
b = {'f':3, 'c':2, 'd':17, 'a':8, 'e':9, 'b':1}

How do you convert a and b to OrderedDict's but make sure that whatever keys b has in common with a, they end up in the same order as those keys in a

cardamom
  • 6,873
  • 11
  • 48
  • 102

4 Answers4

2

Your existing dictionary makes no promises about the ordering. Let's make it an ordered dictionary first:

ordered_a = OrderedDict(a.items())

Now, suppose you have the other dictionary b, and you wish its keys to be in the same order as ordered_a, if they exist, then:

ordered_b = OrderedDict(
    [(k, b[k]) for k in itertools.chain(ordered_a, b.keys() - a.keys()) 
     if k in b])

Here we add the items from b into ordered_b in the same order as ordered_a, where they exist, and then add the remaining items of b in an arbitrary order. This will handle the possibilities that:

  • a contains keys that b does not have; or
  • b contains keys that a does not have.
donkopotamus
  • 22,114
  • 2
  • 48
  • 60
  • Thanks, can see with the first part of your answer you are already saving me from a mistake. `OrderedDict(a)` and `OrderedDict(a.items())` seem to produce something that looks the same but maybe the latter is better. Have tested the second part of your answer and it seems to work – cardamom Dec 06 '17 at 00:32
1

I assume you want it in sorted order. Try this

c = OrderedDict(sorted(a.items()))
balki
  • 26,394
  • 30
  • 105
  • 151
  • Thanks @balki but do you know how to give b the same order as a? Sorting is not so important. Just a fixed order. – cardamom Dec 06 '17 at 00:17
  • cardamom: Just saying "the same order as a" is way too vague. What if there are things (keys) in one that aren't in the other? – martineau Dec 06 '17 at 00:30
  • cardamom: A related issue is you saying you want `b` to be an `OrderedDict` in the same order as `a`—but since `a` is a regular dictionary, the order of **its** contents is arbitrary. – martineau Dec 06 '17 at 00:47
  • @martineau I can see the original question was unclear as to whether it was asking about the specific case where both dictionaries have exactly the same keys or the generic case where one might have more than the other. Now can see an extra problem which you mention - the first two lines imply that I am not aware that for example `{'a':5, 'b':7, 'c':3, 'd':9} == { 'c':3, b':7,'d':9, 'a':5}` and could confuse someone trying to learn Python. Well, the four answers have helped me move forward with my program. People here are meanwhile downvoting and am losing points. Should I delete the question? – cardamom Dec 06 '17 at 02:04
1

If a and b always have exactly the same keys you could just make sure that both ordered dicts are created based on sorted keys:

oa = OrderedDict(sorted(a.items(), key=lambda t: t[0]))
ob = OrderedDict(sorted(b.items(), key=lambda t: t[0]))

or just force b to have whatever order a got:

oa = OrderedDict(a)
ob = OrderedDict((k, b[k]) for k in oa)
Turn
  • 6,656
  • 32
  • 41
1

If you want an OrderedDict with b's items in c's order, iterate over c to produce the ordering:

d = OrderedDict((k, b[k]) for k in c)

However, keep in mind that c's ordering is not guaranteed to be consistent across different executions of the program.

user2357112
  • 260,549
  • 28
  • 431
  • 505