Python: порядок элементов в словаре - PullRequest
3 голосов
/ 26 апреля 2011

Вот мой код 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!

Есть ли способ сохранить исходный порядок элементов, чтобы посты были упорядочены по added в posts_to_return?

Спасибо!

РЕДАКТИРОВАТЬ: Python 2.6, Django 1.3

Ответы [ 7 ]

6 голосов
/ 26 апреля 2011

Использовать 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()
6 голосов
/ 26 апреля 2011

Dicts в Python (и большинство языков) не имеют порядка. Вместо этого вы должны использовать collections.OrderedDict. Это сохранит порядок элементов по мере их добавления. Вы также можете посмотреть встроенную функцию sorted(), если порядок добавления не соответствует порядку, который вы пытаетесь сохранить.

4 голосов
/ 28 марта 2014

Стоит также отметить, что вы можете использовать одну из многих реализаций словаря Python, которая поддерживает ключи в отсортированном порядке.Это очень важно, если вы планируете делать какие-либо вставки в ваш отсортированный диктат.Рассмотрим модуль sortedcontainers , который является реализациями на чистом Python и fast-as-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()]

Существует также сравнение производительности , которое сравнивает несколько популярных опций друг с другом.

3 голосов
/ 26 апреля 2011

Поскольку вы используете Django, вы можете использовать SortedDict ( документы )

1 голос
/ 26 апреля 2011

Поскольку никто еще не обратил на это внимание, я просто отмечу, что документы OrderedDict указывают, что этот рецепт эквивалентен и работает на Python 2.4 и выше.Так что, по крайней мере, вам не нужно кататься самостоятельно.

0 голосов
/ 26 апреля 2011

Вы можете использовать OrderedDict вместо Dict.

from collections import OrderedDict
...
post_list = OrderedDict([(obj.id, obj) for obj in posts])
0 голосов
/ 26 апреля 2011

Вам понадобится заказанный словарь, который будет доступен в Python3.3, насколько я знаю. Так что вам, вероятно, придется заказывать свой результат «вручную». В зависимости от ваших действий (которые вы не показывали), возможно, можно будет просто повторно использовать исходный список сообщений. Но, не зная операций, я могу только догадываться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...