Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OrderedDict Isn't Ordered?

I'm trying to use an OrderedDict, but it keeps being created out of order. For example,

from collections import OrderedDict OrderedDict(a=1,b=2,c=3) 

yields

OrderedDict([('a', 1), ('c', 3), ('b', 2)]) 

rather than the expected

OrderedDict([('a', 1), ('b', 2), ('c', 3)]) 

How can I make sure it's created in the proper order I intend?

like image 701
wogsland Avatar asked Jan 26 '17 04:01

wogsland


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. move_to_end() , and supports reversed() iteration*.

How do I add an OrderedDict in Python?

By browsing the array in order you can refer to the dictionary properly, and the order in array will survive any export in JSON, YAML, etc. Actually, you can load an OrderedDict using json. load(). There is a second parameter which tells the load method to create an OrderedDict object to keep order the same.

Is OrderedDict sorted?

The OrderedDict() is a method of the Collections module that returns an instance of a dict subclass with a method specialized for rearranging dictionary order. The sorted() function returns a sorted list of the specified iterable object. The OrderedDict() method preserves the order in which the keys are inserted.

Is dictionary ordered or unordered?

A dictionary is a collection which is ordered*, changeable and do not allow duplicates. As of Python version 3.7, dictionaries are ordered. In Python 3.6 and earlier, dictionaries are unordered.


2 Answers

collections.OrderedDict keeps track of the order in which elements were added to it. This would work fine in a loop:

c = collections.OrderedDict() for a,b in zip('abc', (1,2,3)):     c[a] = b 

However, the expression OrderedDict(a=1,b=2,c=3) creates an OrderedDict by passing several keyword arguments to its constructor. In Python 2.7, the order of keyword arguments is not guaranteed. If you want that, you'll have to move to Python 3.6, which implements PEP 468, Preserving the order of **kwargs in a function.

The **kwargs syntax in a function definition indicates that the interpreter should collect all keyword arguments that do not correspond to other named parameters. However, Python does not preserved the order in which those collected keyword arguments were passed to the function. In some contexts the order matters. This PEP dictates that the collected keyword arguments be exposed in the function body as an ordered mapping.

like image 96
TigerhawkT3 Avatar answered Oct 08 '22 14:10

TigerhawkT3


It's weird that it hasn't been mentioned already but the representation of OrderedDict shows you how to create it so that the order is kept:

OrderedDict([('a', 1), ('b', 2), ('c', 3)]) 

it's not meant as an obstacle that the representation is like that - it's because that representation can be used to create an identical ordered OrderedDict.


Just for completeness (it has been mentioned already), the order is lost because OrderedDict(a=1, b=2, c=3) catches these arguments as **kwargs, which is a normal unordered-dict. At least until python 3.6 came along and made the promise that the order of the kwargs will be kept when you pass it in as you did:

What’s New In Python 3.6

PEP 468: Preserving Keyword Argument Order

**kwargs in a function signature is now guaranteed to be an insertion-order-preserving mapping.

like image 23
MSeifert Avatar answered Oct 08 '22 15:10

MSeifert