67

Is it possible to retrieve items from a Python dictionary in the order that they were inserted?

Blair Conrad
  • 233,004
  • 25
  • 132
  • 111
readonly
  • 343,444
  • 107
  • 203
  • 205
  • possible duplicate of [Why dictionary values aren't in the inserted order?](http://stackoverflow.com/questions/6061380/why-dictionary-values-arent-in-the-inserted-order) – nbro Jan 10 '15 at 01:52
  • 2
    This question (and outdated accepted answer) is still the #1 result of googling "python dict items by insertion order". If you're reading this, please upvote Brian's 2018 answer. – Rakurai Jan 02 '19 at 18:04

11 Answers11

70

The standard Python dict does this by default if you're using CPython 3.6+ (or Python 3.7+ for any other implementation of Python).

On older versions of Python you can use collections.OrderedDict.

Boris Verkhovskiy
  • 14,854
  • 11
  • 100
  • 103
dF.
  • 74,139
  • 30
  • 130
  • 136
25

As of Python 3.7, the standard dict preserves insertion order. From the docs:

Changed in version 3.7: Dictionary order is guaranteed to be insertion order. This behavior was implementation detail of CPython from 3.6.

So, you should be able to iterate over the dictionary normally or use popitem().

Brian McCutchon
  • 8,354
  • 3
  • 33
  • 45
  • 2
    Lets get this answer upvoted. Additionally from the docs, section 5.5 Dictionaries: "Performing list(d) on a dictionary returns a list of all the keys used in the dictionary, in insertion order (if you want it sorted, just use sorted(d) instead)." – Rakurai Jan 02 '19 at 17:59
20

Use OrderedDict(), available since version 2.7

Just a matter of curiosity:

from collections import OrderedDict
a = {}
b = OrderedDict()
c = OrderedDict()

a['key1'] = 'value1'
a['key2'] = 'value2'

b['key1'] = 'value1'
b['key2'] = 'value2'

c['key2'] = 'value2'
c['key1'] = 'value1'

print a == b  # True
print a == c  # True
print b == c  # False
Diggy.
  • 6,744
  • 3
  • 19
  • 38
rewgoes
  • 656
  • 2
  • 9
  • 23
17

The other answers are correct; it's not possible, but you could write this yourself. However, in case you're unsure how to actually implement something like this, here's a complete and working implementation that subclasses dict which I've just written and tested. (Note that the order of values passed to the constructor is undefined but will come before values passed later, and you could always just not allow ordered dicts to be initialized with values.)

class ordered_dict(dict):
    def __init__(self, *args, **kwargs):
        dict.__init__(self, *args, **kwargs)
        self._order = self.keys()

    def __setitem__(self, key, value):
        dict.__setitem__(self, key, value)
        if key in self._order:
            self._order.remove(key)
        self._order.append(key)

    def __delitem__(self, key):
        dict.__delitem__(self, key)
        self._order.remove(key)

    def order(self):
        return self._order[:]

    def ordered_items(self):
        return [(key,self[key]) for key in self._order]


od = ordered_dict()
od["hello"] = "world"
od["goodbye"] = "cruel world"
print od.order()            # prints ['hello', 'goodbye']

del od["hello"]
od["monty"] = "python"
print od.order()            # prints ['goodbye', 'monty']

od["hello"] = "kitty"
print od.order()            # prints ['goodbye', 'monty', 'hello']

print od.ordered_items()
# prints [('goodbye','cruel world'), ('monty','python'), ('hello','kitty')]
Eli Courtwright
  • 186,300
  • 67
  • 213
  • 256
  • Is order_dict( ('key_a','value_a'), ('key_b','value_b') ) ordered correctly? Looks like _order would be set to self.keys() in __init__, which is ordered in the hash-ordering, not the order it was entered? Just curious. – Brian M. Hunt Dec 09 '08 at 20:57
  • You're correct, which is why I said, "the order of values passed to the constructor is undefined but will come before values passed later". It would be possible to order those properly, but I wasn't sure whether that was a desired behavior, since arguably such objects are inserted simultaneously. – Eli Courtwright Dec 10 '08 at 22:13
5

You can't do this with the base dict class -- it's ordered by hash. You could build your own dictionary that is really a list of key,value pairs or somesuch, which would be ordered.

Serafina Brocious
  • 30,433
  • 12
  • 89
  • 114
  • 2
    Your dictionary implementation can instead use a standard dictionary and a list - the dictionary stores the key->value associations, and the list stores keys in the order they are inserted. – Binil Thomas Sep 13 '08 at 21:56
5

Or, just make the key a tuple with time.now() as the first field in the tuple.

Then you can retrieve the keys with dictname.keys(), sort, and voila!

Gerry

Gerry
  • 1,303
  • 1
  • 10
  • 16
  • 6
    This makes it impossible to look up entries in the dict without knowing exactly when you inserted them. It's no better than a list of key-value pairs. – user2357112 Jun 04 '14 at 03:03
3

I've used StableDict before with good success.

http://pypi.python.org/pypi/StableDict/0.2

jaywgraves
  • 105
  • 6
1

Or use any of the implementations for the PEP-372 described here, like the odict module from the pythonutils.

I successfully used the pocoo.org implementation, it is as easy as replacing your

my_dict={}
my_dict["foo"]="bar"

with

my_dict=odict.odict()
my_dict["foo"]="bar"

and require just this file

Davide
  • 17,098
  • 11
  • 52
  • 68
0

It's not possible unless you store the keys in a separate list for referencing later.

Jeremy Cantrell
  • 26,392
  • 13
  • 55
  • 78
-1

What you can do is insert the values with a key representing the order inputted, and then call sorted() on the items.

>>> obj = {}
>>> obj[1] = 'Bob'
>>> obj[2] = 'Sally'
>>> obj[3] = 'Joe'
>>> for k, v in sorted(obj.items()):
...     print v
... 
Bob
Sally
Joe
>>> 
A.J. Uppal
  • 19,117
  • 6
  • 45
  • 76
  • 2
    If we didn't already need the key for other purposes, we would use a list. This does nothing a list doesn't do better. – user2357112 Jun 04 '14 at 02:53
  • 1
    @user2357112, however, this expresses another method of doing **what the OP asked**. The OP did not ask how to print items in the order they were inserted, the OP said how to print items **in a `dict`**. Big difference. – A.J. Uppal Jun 04 '14 at 02:56
  • 1
    You've changed the format of the dict to the point of making it unuseful for the original purpose, though. If the dict was originally associating, say, names to phone numbers, you've gained a consistent iteration order, but you have no idea what Bob's phone number is. – user2357112 Jun 04 '14 at 02:57
-1

if you don't need the dict functionality, and only need to return tuples in the order you've inserted them, wouldn't a queue work better?