Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OrderedDict in python 3 - how to get the keys in order?

In python 2 when using an OrderedDict I was able to get the keys in the order they were inserted by simply using the keys method that returned a list. In python 3 however:

rows = OrderedDict()
rows[0]=[1,2,3]
rows[1]=[1,2,3]
image = [rows[k] for k in rows.keys()[:2]]

I get:

Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: 'odict_keys' object is not subscriptable

I certainly can do list(rows)[:2] as advised for instance here - but is this guaranteed to get me the keys in order ? Is this the one right way ?

UPDATE: the python 2 code would be better as:

image = [v for v in rows.values()[:2]]

which of course still blows with the same error on python 3

like image 797
Mr_and_Mrs_D Avatar asked May 24 '17 00:05

Mr_and_Mrs_D


People also ask

How are Python dictionary Keys ordered?

Python 3.6 (CPython) As of Python 3.6, for the CPython implementation of Python, dictionaries maintain insertion order by default. This is considered an implementation detail though; you should still use collections. OrderedDict if you want insertion ordering that's guaranteed across other implementations of Python.

Does dict keys return keys in order?

Answer. No, there is no guaranteed order for the list of keys returned by the keys() function. In most cases, the key list is returned in the same order as the insertion, however, that behavior is NOT guaranteed and should not be depended on by your program.

Does dict keys preserve order?

Standard dict objects preserve order in the reference (CPython) implementations of Python 3.5 and 3.6, and this order-preserving property is becoming a language feature in Python 3.7.

Does Python dictionary keys maintain order?

Since dictionaries in Python 3.5 don't remember the order of their items, you don't know the order in the resulting ordered dictionary until the object is created. From this point on, the order is maintained. Since Python 3.6, functions retain the order of keyword arguments passed in a call.


1 Answers

@mglison is right. Because OrderedDict follows the iterator protocol, it is guaranteed to yield the keys in the correct order to list():

However, like @mglison also mentioned,itertools.islice() would be better and more efficent than simply using list and subscripting. After timing both methods multiple times using the timeit module, the itertools method was roughly 2x faster. Here are the exact numbers:

After getting the average time of running both list(itertools.islice(rows, 2)) and list(rows.keys())[:2](notice I'm casting the result of islice() to a list) multiple times, it appears that using the latter method is actual slightly faster:

---------------------------------------------------------------
|  list(itertools.islice(rows, 2))   |    1.5023668839901838  |      
---------------------------------------------------------------
|  list(rows.keys())[:2]             |    1.495460570215706   |      
---------------------------------------------------------------

However, the difference of the two numbers is so small, I really would not make much of difference which method you use. Just choose the method which is the most readable and understandable for your specific case.

like image 165
Christian Dean Avatar answered Sep 17 '22 23:09

Christian Dean