Можно ли получить элементы из словаря Python в том порядке, в котором они были вставлены?
Этот вопрос (и устаревший принятый ответ) по-прежнему является результатом №1 поиска в Google «элементов Python dict по порядку вставки». Если вы читаете это, проголосуйте за ответ Брайана 2018 года.






Вы не можете сделать это с базовым классом dict - он упорядочен по хешу. Вы можете создать свой собственный словарь, который на самом деле представляет собой список пар ключей, значений или чего-то подобного, которые будут упорядочены.
Вместо этого ваша реализация словаря может использовать стандартный словарь и список - словарь хранит ассоциации ключ-> значение, а список хранит ключи в том порядке, в котором они вставлены.
Стандартный Python dict делает это по умолчанию, если вы используете CPython 3.6+ (или Python 3.7+ для любой другой реализации Python).
В более старых версиях Python вы можете использовать collections.OrderedDict.
Кажется, что этот ответ был обновлен в соответствии с последним правильным ответом (который также является ответом Брайана), поэтому приведенные выше комментарии больше не актуальны.
Остальные ответы верны; это невозможно, но вы можете написать это сами. Однако, если вы не знаете, как на самом деле реализовать что-то подобное, вот полная и рабочая реализация, диктуемая подклассами, которую я только что написал и протестировал. (Обратите внимание, что порядок значений, переданных в конструктор, не определен, но будет предшествовать значениям, переданным позже, и вы всегда можете просто не разрешить инициализацию упорядоченных диктовок значениями.)
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')]
Правильно ли заказан order_dict (('key_a', 'value_a'), ('key_b', 'value_b'))? Похоже, что _order будет установлен на self.keys () в в этом, который упорядочен в порядке хеширования, а не в том порядке, в котором он был введен? Просто любопытно.
Вы правы, поэтому я сказал: «Порядок значений, передаваемых в конструктор, не определен, но будет до значений, переданных позже». Их можно было бы правильно заказать, но я не был уверен, было ли это желаемым поведением, поскольку, возможно, такие объекты вставляются одновременно.
если вам не нужны функции dict и вам нужно возвращать кортежи только в том порядке, в котором вы их вставили, не будет ли очередь работать лучше?
Раньше я успешно использовал StableDict.
Или просто сделайте ключ кортежем с time.now () в качестве первого поля в кортеже.
Затем вы можете получить ключи с помощью dictname.keys (), sort и вуаля!
Джерри
Это делает невозможным поиск записей в dict, не зная точно, когда вы их вставили. Это не лучше, чем список пар ключ-значение.
Это невозможно, если вы не сохраните ключи в отдельном списке для использования позже.
Или используйте любую из реализаций для PEP-372, описанных здесь, например модуль odict из pythonutils.
Я успешно использовал реализацию pocoo.org, это так же просто, как заменить ваш
my_dict = {}
my_dict["foo"] = "bar"
с
my_dict=odict.odict()
my_dict["foo"] = "bar"
и требуется только этот файл
Что вы можете сделать, так это вставить значения с помощью ключа, представляющего введенный порядок, а затем вызвать sorted() для элементов.
>>> obj = {}
>>> obj[1] = 'Bob'
>>> obj[2] = 'Sally'
>>> obj[3] = 'Joe'
>>> for k, v in sorted(obj.items()):
... print v
...
Bob
Sally
Joe
>>>
Если бы нам еще не понадобился ключ для других целей, мы бы использовали список. Это не делает ничего лучше, чем список.
@ user2357112, однако, это выражает другой метод выполнения что ОП спросил. OP не спрашивал, как печатать элементы в том порядке, в котором они были вставлены, OP сказал, как печатать элементы в dict. Большая разница.
Однако вы изменили формат словаря до такой степени, что он стал бесполезным для первоначальной цели. Если dict изначально связывает, скажем, имена с телефонными номерами, вы получили постоянный порядок итераций, но вы не знаете, какой номер телефона у Боба.
Используйте OrderedDict (), доступный с версии 2.7.
Просто любопытство:
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
Начиная с Python 3.7, стандартный dict сохраняет порядок вставки. Из документы:
Changed in version 3.7: Dictionary order is guaranteed to be insertion order. This behavior was implementation detail of CPython from 3.6.
Итак, вы должны иметь возможность перебирать словарь в обычном режиме или использовать popitem().
Давайте проголосуем за этот ответ. Дополнительно из документации, раздел 5.5 Словари: «Выполнение list (d) в словаре возвращает список всех ключей, используемых в словаре, в порядке вставки (если вы хотите, чтобы он был отсортирован, просто используйте вместо этого sorted (d))».
возможный дубликат Почему значения словаря не во вставленном порядке?