Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python OrderedDict iteration

Why does my python OrderedDict get initialized 'out of order'?

The solution here is less intriguing than the explanation. There's something here I just don't get, and perhaps an expanation would help others as well as me.

>>> from collections import OrderedDict  >>> spam = OrderedDict(s = (1, 2), p = (3, 4), a = (5, 6), m = (7, 8))  >>> spam OrderedDict([('a', (5, 6)), ('p', (3, 4)), ('s', (1, 2)), ('m', (7, 8))])  >>> for key in spam.keys(): ...    print key     ... #  this is 'ordered' but not the order I wanted.... a p s m  # I was expecting (and wanting): s p a m 
like image 727
neil.millikin Avatar asked May 14 '13 21:05

neil.millikin


People also ask

Is OrderedDict obsolete?

No it won't become redundant in Python 3.7 because OrderedDict is not just a dict that retains insertion order, it also offers an order dependent method, OrderedDict.

How does OrderedDict work in Python?

OrderedDict preserves the order in which the keys are inserted. A regular dict doesn't track the insertion order and iterating it gives the values in an arbitrary order. By contrast, the order the items are inserted is remembered by OrderedDict.

How do I create an empty OrderedDict in Python?

OrderedDict is part of python collections module. We can create an empty OrderedDict and add items to it. If we create an OrderedDict by passing a dict argument, then the ordering may be lost because dict doesn't maintain the insertion order. If an item is overwritten in the OrderedDict, it's position is maintained.


1 Answers

From the docs:

The OrderedDict constructor and update() method both accept keyword arguments, but their order is lost because Python’s function call semantics pass-in keyword arguments using a regular unordered dictionary.

So initialization loses the ordering, because it's basically calling a constructor with **kwargs.

Edit: In terms of a solution (not just an explanation)—as pointed out in a comment by the OP, passing in a single list of tuples will work:

>>> from collections import OrderedDict >>> spam = OrderedDict([('s',(1,2)),('p',(3,4)),('a',(5,6)),('m',(7,8))]) >>> for key in spam: ...     print(key) ... s p a m >>> for key in spam.keys(): ...     print(key) ... s p a m 

This is because it's only getting a single argument, a list.

like image 141
Chris Krycho Avatar answered Oct 06 '22 00:10

Chris Krycho