[Django]-Python: Element order in dictionary

6đź‘Ť

âś…

Use SortedDict instead of dict (from django.utils.datastructures import SortedDict)

SortedDict maintains it’s order in it’s keyOrder attribute. So you can manipulate the ordering without reconstructing dict if you want to. For example, to reverse the SortedDict’s order just use keyOrder.reverse()

post_list = SortedDict([(obj.id, obj) for obj in posts])
# reversing the post order in-place
post_list.keyOrder.reverse()
👤Imran

6đź‘Ť

Dicts in python (and most languages) have no order. You should instead use collections.OrderedDict. This will retain the order of items as they are added. You can also look at the sorted() builtin if the order of addition isn’t the order you’re trying to preserve.

👤Daenyth

4đź‘Ť

It’s also worth noting that you can use one of Python’s many dictionary implementations that maintains the keys in sorted order. This is critical if you plan to do any insertions into your sorted dict. Consider the sortedcontainers module which is pure-Python and fast-as-C implementations. There’s a SortedDict implementation that supports exactly what you need.

>>> from sortedcontainers import SortedDict
>>> posts = Post.objects.all().order_by('-added')[:20] # ordered by 'added'
>>> post_list = SortedDict([(obj.id, obj) for obj in posts])
>>> # ... some operations with dictionary elements go here ...
>>> # This is now automatically ordered by id:
>>> posts_to_return = [post for post_id, post in post_list.items()]

There’s also a performance comparison that benchmarks several popular options against one another.

👤GrantJ

3đź‘Ť

As you are using Django you could use SortedDict (docs)

👤arie

1đź‘Ť

Because no one has drawn attention to it yet, I’ll simply note that the OrderedDict docs indicate that this recipe is equivalent and works on Python 2.4 and up. So at least you don’t have to roll your own.

👤senderle

0đź‘Ť

You would need an ordered dictionary, which will be available in Python3.3 as far as I know. So you will probably have to order your result “by hand”. Depending on your operations (which you havn’t shown) it might be possible to just reuse the original posts list. But without knowing the operations, I can only guess.

👤Achim

0đź‘Ť

You can use an OrderedDict instead of a Dict.

from collections import OrderedDict
...
post_list = OrderedDict([(obj.id, obj) for obj in posts])
👤Pete Aykroyd

Leave a comment