137

Code:

d = {'a': 0, 'b': 1, 'c': 2}
l = d.keys()

print l

This prints ['a', 'c', 'b']. I'm unsure of how the method keys() determines the order of the keywords within l. However, I'd like to be able to retrive the keywords in the "proper" order. The proper order of course would create the list ['a', 'b', 'c'].

Raymond Hettinger
  • 216,523
  • 63
  • 388
  • 485
rectangletangle
  • 50,393
  • 94
  • 205
  • 275
  • 4
    If Python dictionaries are like most, they're actually hash tables. Among other things, that means the order of the keys isn't guaranteed or even specified. In particular, it wouldn't remember the order in which keys are added. – cHao Apr 12 '11 at 00:28
  • possible duplicate of [Why is python ordering my dictionary like so?](http://stackoverflow.com/questions/526125/why-is-python-ordering-my-dictionary-like-so) – alko Dec 10 '13 at 20:03
  • 4
    @cHao: This essentually means that your program will be indeterministic if you loop over the elements in a dictionary? – HelloGoodbye Jan 27 '14 at 13:03
  • 5
    @HelloGoodbye: I wouldn't go that far; there's still very predictable behavior there. Each full iteration sees exactly one of each key/value pair. And in *most* languages, you'll even see them in the same order each time. Unless the docs guarantee a particular order, though, you shouldn't count on it being the order you want. (Some languages (like Perl) will actually randomize the order a bit -- allegedly for security reasons, but i think it's really just to shake you loose from the habit of relying on unspecified behavior. :) I don't *think* Python is quite that evil, but eh...) – cHao Jan 27 '14 at 16:19
  • 1
    The order will be the same providing the dict has not been modified. From the manual: "If items(), keys(), values(), iteritems(), iterkeys(), and itervalues() are called with no intervening modifications to the dictionary, the lists will directly correspond. This allows the creation of (value, key) pairs using zip(): pairs = zip(d.values(), d.keys())." – steveayre Apr 29 '15 at 22:58
  • This isn't working for me, at least not in python 3.4. I'm creating a simple 4-key dictionary and immediately loop over with .keys(), and the order is lost. – sfranky Sep 03 '15 at 12:21
  • python 2.7.10: >>> d = {'what':1, 'the':2, 'heck':3, 'is':4, 'this':5} >>> d.keys() ['this', 'what', 'heck', 'the', 'is'] – sfranky Sep 03 '15 at 12:54
  • 2
    @sfranky I think what steveayre meant is that the order is the same between what you obtain using the different methods mentioned, not the same as the ordrer in which the elements were written. – bli Mar 14 '16 at 15:38

6 Answers6

213

Python 3.7+

In Python 3.7.0 the insertion-order preservation nature of dict objects has been declared to be an official part of the Python language spec. Therefore, you can depend on it.

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.

Python >=2.7 and <3.6

Use the collections.OrderedDict class when you need a dict that remembers the order of items inserted.

Eugene Yarmash
  • 142,882
  • 41
  • 325
  • 378
87

You could use OrderedDict (requires Python 2.7) or higher.

Also, note that OrderedDict({'a': 1, 'b':2, 'c':3}) won't work since the dict you create with {...} has already forgotten the order of the elements. Instead, you want to use OrderedDict([('a', 1), ('b', 2), ('c', 3)]).

As mentioned in the documentation, for versions lower than Python 2.7, you can use this recipe.

Abhinav Gupta
  • 4,602
  • 2
  • 23
  • 18
  • 22
    Keep in mind, the order of an OrderedDict is the *insertion* order; the keys will only come out in alphabetical order if you inserted them that way. – Hugh Bothwell Apr 12 '11 at 01:10
  • it's what he *showed* as a simplified example; it may or may not have any relation to how he actually plans to use it. I have previously encountered people who expected OrderedDict to return arbitrary insertions in sorted order, and so I felt I should point this out. – Hugh Bothwell Apr 12 '11 at 01:32
  • I'm not convinced that the author was looking for a dictionary preserving the *insertion order*. The key order is generally much more important and it can be achieved with a self-balancing binary search tree. In C++, we have std::set for that. In python, apparently, there's no such thing (built-in). – vvaltchev Apr 28 '21 at 12:37
53
>>> print sorted(d.keys())
['a', 'b', 'c']

Use the sorted function, which sorts the iterable passed in.

The .keys() method returns the keys in an arbitrary order.

Mike Lewis
  • 63,433
  • 20
  • 141
  • 111
  • 13
    This doesn't work if you want the original order and it wasn't sorted. – Simon Oct 19 '17 at 19:47
  • If you sort once, this is good. If you sort inside a loop you're better off with a treap or red-black tree or something - these are available on Pypi. – dstromberg Aug 04 '22 at 15:46
13

From http://docs.python.org/tutorial/datastructures.html:

"The keys() method of a dictionary object returns a list of all the keys used in the dictionary, in arbitrary order (if you want it sorted, just apply the sorted() function to it)."

12

Just sort the list when you want to use it.

l = sorted(d.keys())
Drew
  • 2,269
  • 21
  • 16
1

Although the order does not matter as the dictionary is hashmap. It depends on the order how it is pushed in:

s = 'abbc'
a = 'cbab'

def load_dict(s):
    dict_tmp = {}
    for ch in s:
        if ch in dict_tmp.keys():
            dict_tmp[ch]+=1
        else:
            dict_tmp[ch] = 1
    return dict_tmp

dict_a = load_dict(a)
dict_s = load_dict(s)
print('for string %s, the keys are %s'%(s, dict_s.keys()))
print('for string %s, the keys are %s'%(a, dict_a.keys()))

output:
for string abbc, the keys are dict_keys(['a', 'b', 'c'])
for string cbab, the keys are dict_keys(['c', 'b', 'a'])

Crivella
  • 897
  • 6
  • 11
zehai
  • 21
  • 3
  • 2
    Dictionary in python are insertion ordered only from version 3.6+ [check this](https://stackoverflow.com/questions/39980323/are-dictionaries-ordered-in-python-3-6) – Crivella Feb 08 '19 at 20:01