1

An OrderedDict is ordered by the order items are added to it.

So why is this happening?

I have two dictionaries:

d_names
d_new_names

The second is a re-ordered version of the first. This is because I understand that I cannot re-order an existing OrderedDict - I need to create a new one.

To do this I first create an ordered list:

l_new_names = []
for s_number in d_names:
    for s_week_number in d_names[s_number]:
        l_new_names.append([s_number, s_week_number])

print "l_new_names before sort = %s" % l_new_names
l_new_names.sort()
print "l_new_names after sort = %s" % l_new_names

Then I create and fill the first level of the new dictionary:

d_new_names = ordereddict.OrderedDict()

for s_number, _ in l_new_names:
    if s_number in d_new_names:
        print "NOT creating d_new_names[%s]" % s_number
    else:
        print "creating d_new_names[%s]" % s_number
        d_new_names[s_number] = {}
        d_new_names[s_number][NAME] = d_names[s_number][NAME]

Then I create the second level and fill the dictionary:

for s_number, s_week_number in l_new_names:
    d_new_names[s_number][s_week_number] = {}
    d_new_names[s_number][s_week_number][DATE] = d_names[s_number][s_week_number][DATE]
    d_new_names[s_number][s_week_number][PRICE] = d_names[s_number][s_week_number][PRICE]

When I wrote the dictionary contents to a file I was surprised to see this order:

writing week:13
writing week:15
writing week:14
writing week:16

That is, week 15 precedes week 14.

Upon investigation (printing the OrderedDict each time through the second loop) I found this (number corresponds to loop):

  1. week 13 added; order: 13
  2. week 14 added; order: 13, 14
  3. week 15 added; order: 13, 15, 14
  4. week 16 added; order: 13, 15, 14, 16

Conclusion: during creation and insertion of elements into the OrderedDict, the elements are being inserted in the wrong order. I did not think that was possible.

Can anyone explain what is happening and how I resolve this?

Community
  • 1
  • 1

1 Answers1

3

You are inserting week numbers into a regular dictionary, not an ordered dictionary:

d_new_names[s_number] = {}

Here d_new_names in an ordered dictionary, so the s_number values are kept in insertion order, but the keys refer to normal dictionaries.

Then later you use those normal dictionaries to store per-week information:

d_new_names[s_number][s_week_number] = {}

Your s_week_number week numbers are thus not kept in insertion order, but follow the arbitrary ordering of a normal dictionary instead.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • That's it! I changed the two lines you quote to: `d_new_names[s_po_number] = ordereddict.OrderedDict()` and `d_new_names[s_po_number][s_week_number] = ordereddict.OrderedDict()` and now it works, thanks so much. (6 minutes from question to solution - best I've seen with one of my questions! :) ) [And I would not have found this on my own, cheers!] – Reinstate Monica - Goodbye SE Apr 28 '16 at 11:56
  • 1
    @Wikis had you included a full MCVE I could've made it 3, I'm sure. :-) – Martijn Pieters Apr 28 '16 at 11:57