Question

The idea of this loop was to iterate through a list. If a certain property of an object was not a key of the OrderedDict, it would add it. It is a dictionary of lists of objects

for object in someList:
  if object.DATE not in myOrderedDict:
     myOrderedDict[object.DATE]=[]
  myOrderedDict[object.DATE].append(object)

while it does seem to make the OrderedDict mostly correctly, it ends up out of order when it's printed. Instead of having something like (01/13) (02/13) (03/13) it goes more like (02/13) (03/13) (01/13).
Why does this happen and how can it be fixed?

Was it helpful?

Solution

It would appear that you expect the items in an OrderedDict to be ordered by key, which is not the case. An OrderedDict is ordered by the order items are added to it. From the PEP 372 FAQ:

Does OrderedDict support alternate sort orders such as alphabetical?

No. Those wanting different sort orders really need to be using another technique. The OrderedDict is all about recording insertion order. If any other order is of interest, then another structure (like an in-memory dbm) is likely a better fit.

OTHER TIPS

The pure-Python sortedcontainers module has a SortedDict type that can help you. It maintains the dict keys automatically in sorted order and is well documented and tested. You use it just as you would a dict:

>>> from sortedcontainers import SortedDict
>>> mySortedDict = SortedDict()
>>> for object in someList:
>>>     if object.DATE not in mySortedDict:
>>>         mySortedDict[object.DATE]=[]
>>>     mySortedDict[object.DATE].append(object)
>>> list(mySortedDict.keys())
['(01/13)', '(02/13)', '(03/13)']

The sorted containers module is very fast and has a performance comparison page with benchmarks against alternative implementations.

An OrderedDict is a dict that remembers the order that keys were first inserted. So the order of the dict is the order of the key inserted. It will not sorted your dict by the key.

OrderedDict remembers insertion order, just use a regular dict and sort it before you print it. You can sort your dict alphabetically like this

sorted(myDict, key=myDict.get)

I have mocked up an example of what I think you are getting at, and the OrderedDict does preserve the order you insert in. This may not be what you would want. In that case you can look at the sorted() solution. This should clarify:

import collections

class ob():
    def __init__(self, d, v):
        self.DATE = d
        self.VALUE = v

orderedDict = collections.OrderedDict()
normalDict = {}

someList = [ob('02/13', 2), ob('03/13',3), ob('04/13', 4) , ob('01/13', 5), ob('02/13', 15)]

for a in someList:
  if a.DATE not in orderedDict:
     orderedDict[a.DATE]=[]
     normalDict[a.DATE]=[]
  orderedDict[a.DATE].append(a)
  normalDict[a.DATE].append(a)

orderedDictSorted = collections.OrderedDict(sorted(orderedDict.items()))

print 'Ordered Dict'
print orderedDict.keys()
print 'Dict'
print normalDict.keys()
print 'Ordered Dict Sorted'
print orderedDictSorted.keys()

This functionality has been in ruamel.ordereddict (available from PyPI) for Python 2, since 2007:

from ruamel.ordereddict import sorteddict

(this is a fast C implementation, disclaimer: I am the author of tha t package).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top