views:

305

answers:

4

Fellows:

A Python dictionary is stored in no particular order (mappings have no order), e.g.,

>>> myDict = {'first':'uno','second':'dos','third':'tres'}
myDict = {'first':'uno','second':'dos','third':'tres'}
>>> myDict
myDict
{'second': 'dos', 'third': 'tres', 'first': 'uno'}

While it is possible to retrieve a sorted list or tuple from a dictionary, I wonder if it is possible to make a dictionary store the items in the order they are passed to it, in the previous example this would mean having the internal ordering as {'first':'uno','second':'dos','third':'tres'} and no different.

I need this because I am using the dictionary to store the values as I read them from a configuration file; once read and processed (the values are altered), they have to be written to a new configuration file in the same order as they were read (this order is not alphabetical nor numerical).

Any thoughts?

Edit: Please notice that I am not looking for secondary ways to retrieve the order (like lists), but of ways to make a dictionary be ordered in itself (as it will be in upcoming versions of Python).

+2  A: 

Use a list to hold the key order

Ofri Raviv
quick and dirty. alas, not very compact (can get brittle).
Daren Thomas
This works, but I am looking for a more "natural" way, if there is one. It seems that the OrderedDict suggested by S.Mark is the alternative I was looking for. Unfortunately I am stuck with Python 2.5.1 :(
Arrieta
Not if you encapsulate the dict and list in a single object with dict interface. Which, by the way, is what many Ordered Dict implementations do (don't know about the implementation actually adopted in 2.7)
Vinko Vrsalovic
A: 

Dictionaries in Python are implemented as hash tables, which is why the order appears random. You could implement your own variation of a dict that sorts, but you'd lose out on the convenient syntax. Instead, keep track of the order of the keys, too.

Initialization:

keys = []
myDict = {}

While reading:

myDict[key] = value
keys.append(key)

While writing:

for key in keys:
  print key, myDict[key]
dmazzoni
My keys are not in alphabetical or numerical order :( They can be anything.
Arrieta
You wouldn't need to lose out on any syntax. Simply implement special methods such as __get__() and __set__() etc so enable use of syntax like dict['key'] and dict['key1'] = newvalue.
Isaac Hodes
+8  A: 

Try python 2.7 and above, probably 3.1, there is OrderedDict

http://www.python.org/

http://python.org/download/releases/2.7/

>>> from collections import OrderedDict
>>> d = OrderedDict([('first', 1), ('second', 2),
...                  ('third', 3)])
>>> d.items()
[('first', 1), ('second', 2), ('third', 3)]

PEP 372: Adding an ordered dictionary to collections

S.Mark
Thank you, this is very helpful.
Arrieta
You're welcome!
S.Mark
Nice. But keep in mind that is a new feature of an upcoming Python release and is not available in older versions.
akr
... but I'm stuck with 2.5.1 :(
Arrieta
Or get the source code of the OrderedDict from this patch: http://bugs.python.org/issue5397
Georg
If you look at the PEP (http://www.python.org/dev/peps/pep-0372/) you'll find a list of implementations of ordered dictionaries for older pythons. If performance isn't an issue I'd suggest using their own sample implementation of odict (http://dev.pocoo.org/hg/sandbox/raw-file/tip/odict.py), which you'll be able to swap for the standard library one if you ever upgrade.
Michael Dunn
A: 

Implementations of order-preserving dictionaries certainly do exist.

There is this one in Django, confusingly called SortedDict, that will work in Python >= 2.3 iirc.

Mauve