Package: ruamel.ordereddict
The ordereddict module in shortThis is an implementation of an ordered dictionary with Key Insertion
Order (KIO: updates of values do not affect the position of the key),
Key Value Insertion Order (KVIO, an existing key’s position is removed
and put at the back). The standard library module OrderedDict, implemented
later, implements a subset ofordereddictfunctionality.Sorted dictionaries are also provided. Currently only with Key Sorted
Order (KSO, no sorting function can be specified, but you can specify a
transform to apply on the key before comparison (e.g. string.lower)).This package is hosted on BitBucket and installable from PyPI:pip install ruamel.ordereddictFor Windows there are 32 and 64 bit installable wheels available.Usage:from ruamel.ordereddict import ordereddict
kio = ordereddict()
kvio = ordereddict(kvio=True)
# without relax unordered initalisation is not allowed
d = ordereddict({'a':1, 'b': 2}, relax=True)
sd = sorteddict({'a':1, 'b': 2}) # sorteddict is always relaxedplease note that starting with 0.4.6 you should not import _ordereddict
directlyThis module has been tested under:OScompilerPythonLinux Mint 17gcc 4.8.42.7.13WindowsVisual Studio 20102.7.13-32WindowsVisual Studio 20102.7.13-64Older versions of this module has been tested under
and I expect those to still work:OScompilerPythonWindows XP-64Visual Studio 20102.7.10-32Windows XP-64Visual Studio 20102.7.10-64Windows XP-64Visual Studio 20082.6.9-32Windows XP-64Visual Studio 20082.6.9-64Linux Mint 17gcc 4.8.22.6.9Ubuntu 12.04gcc 4.7.22.7.6Ubuntu 12.04gcc 4.7.22.6.8Ubuntu  8.04gcc 4.2.42.7.6Ubuntu  8.04gcc 4.2.42.5.2Windows XPVisual C++ 2008 Express2.7.6Windows 7 64Windows SDK for Win7 SP12.7.6Ubuntu 12.04gcc 4.6.32.7.3Ubuntu  8.04gcc 4.2.42.6.4Ubuntu  8.04gcc 4.2.42.5.2Ubuntu  8.10gcc 4.3.22.5.4Ubuntu  8.10gcc 4.3.22.4.6Ubuntu  7.04gcc 4.1.22.5.1Ubuntu  7.04gcc 4.1.22.4.4Ubuntu  6.06gcc2.5.1Windows XPVisual Studio 20032.5.1Windows XPVisual C++ 2008 Express2.6.5WindowsMingGW 4.7.02.7.3Solaris 10GCC 4.4.x2.7.3Version 0.4.1 was tested and found working on SuSE Linux Enterprise Server
(GCC 4.1.0 and Intel C/C++ 10.1) by Stuart Stock.MingGW and Solaris were tested and reported to work by Wladimir with version
0.4.5Homehttps://bitbucket.org/ruamel/ordereddictis ordereddict’s home on the web.Clone the repository there if you want to work from the source.http://www.xs4all.nl/~anthon/Python/ordereddictused to be
ordereddict’s home on the web.
There you can still find the links for downloading the older version (0.4.5).InstallationYou can clone and checkout the sources, and then run:python setup.py installBugreportingIf you find any problems, please let me know, but also realise that I
have a spamfilter that catches over 100 emails a day and yours might
get in there unnoticed. So if there is no response within a few days
please try again.Functionalityordereddict has all of the functionality of dict() except that there
is no keyword based initialisation and that you cannot pass a normal
dict to the initialisation of the basic ordereddict (however see the
relax-ed keyword below). sorteddict cannot be initialised from keywords
either, but can be initialised from normal dict (ie. they are always
relaxed).As you probably would expect .keys(), .values(), .items(),
.iterkeys(), itervalues(), iteritems() and “for i in some_ordereddict”
have elements ordered based on the key insertion order (or key value
insertion order if kvio is specified, or sort order for sorteddict).ordered/sorteddicts can be pickled.Some methods have been slightly changed:initialisation of ordereddict takes keywords:kvio: if set to True, then move an existing key on updaterelax: if set to True, the ordereddict is relaxed for its life regarding
initialisation and/or update from unordered data (read a normal dict).initialisation of sorteddict takes keyword:key: specifies a function to apply on key (e.g. string.lower).popitem() takes an optional argument (defaulting to -1) indicating which
key/value pair to return (by default the last one available).dict()/.values()/.items()/.iterdict()/.itervalues()/.iteritems()
all take an optional reverse (default False) parameter that gives
the list reversed order resp. iterates in reverse
(the non-iterator can also be done relatively efficient with e.g.
od.dict().reverse() ).update(): takes an optional relax=True which allows one time
ordereddict update from normal dictionaries regardless of
initialisation time relax setting.In addition to that ordereddict and sorteddict have some extra methods:.index(key) - gives an integer value that is the index of the key.setkeys()/.setvalues()/.setitems(), work like those in the Larosa/Foord
implementation, although they might throw different exceptions:
- setvalues’ argument must be an itereable that returns the same number of
items as the length of the ordereddict
- setitems’ argument is free in length, it performs a clear and adds
the items in order.slice retrieval for alland ordereddict only also has:.setkeys(), works like the one in the Larosa/Foord
implementation. Argument must be an itereable returning a permutation of the
existing keys ( that implies having the same length as the ordereddict).reverse()  - reverses the keys in place.insert(position, key, value) - this will put a key at a particular position
so that afterwards .index(key) == position, if the key was already there
the original position (and value) is lost to the new position. This often
means moving keys to new positions!slice deletion/assignment:stepped deletion could be optimized a bit (individual items are deleted
which can require memmoving multiple items)assignment only from OrderedDict (with the same length as the slice). This
could also be optimised as I first delete, then insert individual items.
If the assigned items contain keys that are still there after the deletion
‘phase’ then retrieving that slice does not always give the original
assigned ordereddict (depending on the position of the items
with those keys in either ordereddict).rename(oldkey, newkey) renames a key, but keeps the items position and valueThe new OrderedDict in the standard collections moduleWith Python 3.1 and backported to 2.7 there is an OrderedDict class
available in the collections modules. Raymond Hettinger indicated in
2009 at EuroPython that he preferred to start from a minimal
OrderedDict instead of using the Larosa/Foord
implementation. Unfortunately the available tests (for the
functionality that the simple collections.OrderedDict supports) were
not used either resulting in preventable bugs like repr initially not
working on recursive OrderedDicts.ordereddict (and the Larosa/Foord implementation) is essentially
a superset of collections.OrderedDict, but there are a few
differences:OrderedDict is by default relax-ed.repr of recursive OrderedDict does not give any indication of the
value of the recursive key, as it only displays…. ordereddict
displaysordereddict([…])as value. Just using the dots like
OrderedDict does is going to be ambiguous as soon as you have two different
types A and B and nest A in B in A or B in B in A.some newer build-in functions available in OrderedDict are not
available in ordereddict ( __reversed__, viewkeys, viewvalues, viewitems).All of the differences can be straightened out in small (70 lines of
Python) OrderedDict wrapper around ordereddict. With this wrapper the
OrderedDict tests in the standard test_collections.py all pass.Testingtestordereddict.py in the test subdirectory has been used to test the module.
You can use:python testordereddictto run the tests (py.test support has been dropped as newer versions
of py.test were not compatible).There is a somewhat patched copy of the python lib/Test dictionary testing
routines included as well, it fails on the _update test however
because the default is not to use a relaxed ordereddict.
You can run it with:cd test/unit
python test_dict.pyTo Doimplement Value Sorted Order (VSO: specify value=True for normal
value comparison), or a value rewrite function for VSO ( e.g.
value=string.lower )implement Item Sorted Order (ISO): compare value then key ( the other way
around would not make sense with unique keys, but we might have
non-unique values).implement slice deletion for sorteddictmore testing of sorteddict functionalityspeedtest slicesspeedtest sorteddictcheck on the test_update unittest in test_dict.pyTo Considercomparing ordereddicts (as per Larosa/Foord)implement the whole (optionally) using pointers in the DictObject Items
(Faster on insertion/deletion, slower on accessing slices, makes
implementing algorithms somewhat more difficult), would have to seperate
code for sorteddict as key position determination would be much slower.supply a pure Python implementation of exactly the functionality in
ordereddicttest on older versions (< 2.4) of Python and make portable (if this can
be done without too much clutter) or port.test on the Macoptimise searching for an item pointer for sorteddict with binary search
(for deletion)Background informationordereddict is directly derived from Python’s own dictobject.c file.
The extensions and the representation of ordereddicts() are based
on Larosa/Foord’s excellent pure Python OrderedDict() module
(http://www.voidspace.org.uk/python/odict.html).The implemenation adds a vector of pointers to elements to the basic
dictionary structure and keeps this vector compact (and in order) so
indexing is fast. The elements do not know about their position (so
nothing needs to be updated there if that position changes, but then
finding an item’s index is expensive.  Insertion/deletion is also relatively
expensive in that on average half of the vector of pointers needs to
be memmove-d one position.
There is also a long value for bit info like kvio, relaxed.The sorteddict structure has an additional 3 pointers of which only
one (sd_key) is currently used (the others are sd_cmp and sd_value).SpeedBased on some tests with best of 10 iterations of 10000 iterations of various
functions under Ubuntu 7.10 (see test/timeordereddict.py and test/ta.py):Results in seconds:

-------------------------------   dict         ordereddict  Larosa/Ford  collections
                                                            OrderedDict  OrderedDict
empty                             0.023        0.025        0.023        0.024
create_empty                      0.028        0.031        0.147        0.329
create_five_entry                 0.037        0.042        0.384        0.558
create_26_entry                   0.187        0.203        1.494        1.602
create_676_entry                  5.330        5.574       36.797       34.810
get_keys_from_26_entry            0.209        0.231        1.501        1.762
pop_5_items_26_entry              0.219        0.247        1.952        1.864
pop_26_items_676_entry            7.550        8.127       46.578       41.851
popitem_last_26_entry             0.203        0.225        1.624        1.734
popitem_last_676_entry            5.285        5.534       36.912       34.799
popitem_100_676_entry          --------        5.552       36.577     --------
walk_26_iteritems              --------        0.494        2.792        2.238
-------------------------------   dict         ordereddict  Larosa/Ford  collections
                                                            OrderedDict  OrderedDict

empty                             0.930     1.000           0.950        0.966
create_empty                      0.909     1.000           4.728       10.594
create_five_entry                 0.892     1.000           9.201       13.374
create_26_entry                   0.923     1.000           7.368        7.901
create_676_entry                  0.956     1.000           6.601        6.245
get_keys_from_26_entry            0.908     1.000           6.508        7.641
pop_5_items_26_entry              0.888     1.000           7.916        7.559
pop_26_items_676_entry            0.929     1.000           5.732        5.150
popitem_last_26_entry             0.901     1.000           7.222        7.712
popitem_last_676_entry            0.955     1.000           6.670        6.288
popitem_100_676_entry          --------     1.000           6.588     --------
walk_26_iteritems              --------     1.000           5.653        4.532WhyBecause I am orderly ;-O, and because I use dictionaries to
store key/value information read from some text file quite often.
Unfortunately comparing those files with diff when written from
normal dictionaries often obfucates changes because of the reordering
of lines when key/value pairs are added and then written.I have special routine for YAML files that takes lines like:- key1: val1
- key2: val3
- key3:
    - val3a
    - val3b(i.e. a list of key-value pairs) directly to a single ordered dictionary
and back. (I find it kind of strange to finally have a structured,
human readeable, format that does not try to preserve the
order of key-value pairs so that comparing files is difficult with
‘standard’ text tools).Older versionshttp://www.xs4all.nl/~anthon/Python/ordereddictused to be
ordereddict’s home on the web.There you can still find the links for downloading the older version (0.4.5).History0.4.13: 2017-0723
-0.4.92015-08-10typos fixed by Gianfranco Costamagna0.4.82015-05-31dependent on ruamel.baseversion number in a single placeusing py.test under toxgenerate wheel for 32/64bit py26/py27 on windows0.4.62014-01-18Move to ruamel namespace, hosted on bitbucket, MIT LicenseTesting with tox0.4.52012-06-17Fix for a bug while inserting last item again beyond last position (reportedby Volkan Çetin / volki tolki ( cetinv at gmail.com )Fix for repeated deletion and insertion fail. Found by and solution providedby Darren Dowker (including tests). Also found by Fabio Zadronzy (includinga less elegant fix).applied reindent to .py and astyle to .c files0.4.32009-05-11Fix for a bug in slicing SortedDicts.Found by, and fix provided by, Migel Anguel (linos.es)0.4.22009-03-27Bug found and by Alexandre Andrade and Fabio Zadrozny indoing deepcopy0.4.12007-11-06Bug found and fixed by Fabio Zadrozny on resizing dictionaries0.42007-10-30added pickling, added relaxed initialisation/update (from unordered dicts)added KVIO (Key Value Insertion Order ie. key moves to back on update)implemented sorteddict, with KSO, Key Sorted Order. You can specifya function for key transformation before comparison (such as string.lower)sorteddict does not have all of the ordereddict methods as not all makesense (eg. slice assignment, rename, setkeys)0.32007-10-24added setkeys/setvalues/setitems; slice retrieval, deletion, assignment.rename(oldkey, newkey) rename a key keeping same value and position.index() of non-existing key now returns ValueError instead of SystemErrorChanged the module name to _ordereddict (from ordereddict), as JasonKirstland probably rightfully suggested that any private implementationlikely has the (file)name ordereddict.py. A modulename with leadingunderscore seams more common for extension modules anyway.0.2a2007-10-16Solved the potential GC problem on Windows0.22007-10-16First release, with some tests, and possible still a GC problemwith Windows.0.12007-10-..This version was never released. While testing it I was far in writingan email to comp.lang.python about why timing with timeit did seem tobe memory hungry ….and then I realised ordereddict had a memory leak %-)