Python:字典中的元素顺序
这是我的Django代码,但它的表现和我预期的不太一样:
posts = Post.objects.all().order_by('-added')[:20] # ordered by 'added'
post_list = dict([(obj.id, obj) for obj in posts])
# ... some operations with dictionary elements go here ...
posts_to_return = [post for post_id, post in post_list.items()] # order by 'id' now!
有没有办法保持原来的元素顺序,这样在posts_to_return
中,帖子就可以按照added
的顺序排列呢?
谢谢!
编辑:使用的是Python 2.6和Django 1.3
7 个回答
4
值得一提的是,Python有很多字典的实现方式,其中一些可以保持键的顺序是排好序的。如果你打算在这个有序字典里插入数据,这一点非常重要。你可以看看sortedcontainers模块,它是用纯Python写的,速度跟C语言一样快。里面有一个叫SortedDict的实现,正好满足你的需求。
>>> 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()]
另外,还有一个性能比较,可以让你看看几个流行的选项之间的表现如何。
6
在Python(以及大多数编程语言)中,字典是没有顺序的。这意味着你添加的内容顺序可能会被打乱。如果你想保持添加的顺序,可以使用collections.OrderedDict
。这样的话,添加的项目顺序就会被保留下来。如果你想要的顺序不是添加的顺序,你也可以使用内置的sorted()
函数来排序。
6
使用 SortedDict 替代普通的 dict(from django.utils.datastructures import SortedDict
)
SortedDict 会保持它的顺序,这个顺序保存在 keyOrder
属性里。所以如果你想改变顺序,可以直接操作这个属性,而不需要重新构建一个新的 dict。比如,如果你想把 SortedDict 的顺序反转,只需使用 keyOrder.reverse()
就可以了。
post_list = SortedDict([(obj.id, obj) for obj in posts])
# reversing the post order in-place
post_list.keyOrder.reverse()