Python OrderedDict not keeping element order

25,029

Your problem is that you are constructing a dict to give the initial data to the OrderedDict - this dict doesn't store any order, so the order is lost before it gets to the OrderedDict.

The solution is to build from an ordered data type - the easiest being a list of tuples:

>>> from collections import OrderedDict
>>> od = OrderedDict([((0, 0), [2]), ((0, 1), [1, 9]), ((0, 2), [1, 5, 9])])
>>> od
OrderedDict([((0, 0), [2]), ((0, 1), [1, 9]), ((0, 2), [1, 5, 9])])

It's worth noting that this is why OrderedDict uses the syntax it does for it's string representation - string representations should try to be valid Python code to reproduce the object where possible, and that's why the output uses a list of tuples instead of a dict.

Edit: As of Python 3.6, kwargs is ordered, so you can use keyword arguments instead, provided you are on an up-to-date Python version.

As of 3.7, this is also true for dicts (it was for CPython in 3.6, but the language spec didn't specify it, so using OrderedDict was still required for compatibility). This means if you can assume a 3.7+ environment, you can often drop OrderedDict altogether, or construct one from a regular dict if you need a specific feature (e.g: order to matter for equality).

Share:
25,029
Admin
Author by

Admin

Updated on June 27, 2020

Comments

  • Admin
    Admin almost 4 years

    I'm trying to create an OrderedDict object but no sooner do I create it, than the elements are all jumbled.

    This is what I do:

    from collections import OrderedDict
    od = OrderedDict({(0,0):[2],(0,1):[1,9],(0,2):[1,5,9]})
    

    The elements don't stay in the order I assign

    od
    OrderedDict([((0, 1), [1, 9]), ((0, 0), [2]), ((0, 2), [1, 5, 9])])
    

    docs.python.org doesn't have an example and I can't figure out why the order is getting jumbled. Any help is greatly appreciated.

  • Eric Smith
    Eric Smith almost 10 years
    Also of note, passing names/values to the constructor isn't enough to set the order. >>> from collections import OrderedDict >>> OrderedDict(one=1, two=2, three=3, four=4) OrderedDict([('four', 4), ('one', 1), ('three', 3), ('two', 2)])
  • Gareth Latty
    Gareth Latty almost 10 years
    @EricSmith Indeed, for the same reason - variable keyword args (**kwargs) in Python are stored as a dictionary - so when that happens, the order is lost as before. Note that PEP-468 has a simple solution to this - use an OrderedDict for kwargs, not a feature yet, but maybe some day.
  • Copperfield
    Copperfield about 7 years
    @GarethLatty now in python 3.6 they implemented PEP-468