2011-04-26 109 views
3

這是我的Django代碼無法按預期工作:Python:字典中的元素順序

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! 

有沒有辦法保持原始元素順序,所以帖子將由addedposts_to_return中排序?

謝謝!

編輯: Python 2.6,Django 1.3

回答

6

使用SortedDict而不是字典的(from django.utils.datastructures import SortedDict

SortedDict維持它的順序是keyOrder屬性。所以,如果你願意,你可以在不重構字典的情況下操縱順序。例如,扭轉SortedDict的訂單隻用keyOrder.reverse()

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

謝謝! arie比較快,但由於這個例子我接受了你的答案。 – 2011-04-27 06:55:36

6

日文N3 N4 N5沒有秩序。你應該改用collections.OrderedDict。這將保留添加項目的順序。如果添加順序不是您要保留的順序,您還可以查看內建的sorted()

+0

Django的意思是,我必須堅持python 2.x – 2011-04-26 14:58:08

+0

@ Silverlight Light:你有沒有在[py2.4中的OrderedDict]中看到「see also」位(http://code.activestate.com /食譜/ 576693 /)? – Daenyth 2011-04-26 15:04:04

+0

@Silver Light:OrderedDict是Python 2.7x標準庫的一部分 – Imran 2011-04-26 15:22:54

0

您需要一個有序的字典,據我所知,它將在Python3.3中可用。所以你可能必須「手工」訂購你的結果。根據您的操作(您沒有顯示),可能只是重新使用原始帖子列表。但是不知道這些行動,我只能猜測。

0

您可以使用OrderedDict而不是字典。

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

因爲沒有人提請注意它,但我會簡單地注意到,OrderedDict文檔表明this recipe相當於和作品上的Python 2.4及以上。所以至少你不必自己推出。

3

當你正在使用Django,你可以使用SortedDictdocs

4

另外值得一提的是,你可以使用Python維持在有序的按鍵多的詞典實現之一。如果您打算對已排序的字典進行任何插入,這是至關重要的。考慮一下純Python和快速C實現的sortedcontainers module。有一個支持你需要的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()] 

還有一個performance comparison基準幾個流行的選項相互依賴。