Упорядоченный номер не заказан?
Я пытаюсь использовать OrderedDict
, но он продолжает создаваться не по порядку. Например,
from collections import OrderedDict
OrderedDict(a=1,b=2,c=3)
дает
OrderedDict([('a', 1), ('c', 3), ('b', 2)])
а не ожидаемый
OrderedDict([('a', 1), ('b', 2), ('c', 3)])
Как я могу убедиться, что он создан в правильном порядке, который я намерен?
Ответы
Ответ 1
collections.OrderedDict
отслеживает порядок, в котором элементы были добавлены к нему. Это будет нормально работать в цикле:
c = collections.OrderedDict()
for a,b in zip('abc', (1,2,3)):
c[a] = b
Однако выражение OrderedDict(a=1,b=2,c=3)
создает OrderedDict
, передавая несколько аргументов ключевого слова его конструктору. В Python 2.7 порядок аргументов ключевого слова не гарантируется. Если вы этого хотите, вам нужно перейти на Python 3.6, который реализует PEP 468, Сохранение порядка ** kwargs в функции.
Синтаксис **kwargs
в определении функции указывает, что интерпретатор должен собирать все аргументы ключевого слова, которые не соответствуют другим именованным параметрам. Однако Python не сохранил порядок, в котором те собранные аргументы ключевого слова были переданы функции. В некоторых контекстах порядок имеет значение. Этот PEP диктует, что собранные аргументы ключевого слова будут отображаться в теле функции как упорядоченное сопоставление.
Ответ 2
Странно, что он уже не упоминался, но представление OrderedDict
показывает вам, как его создать, чтобы сохранить порядок:
OrderedDict([('a', 1), ('b', 2), ('c', 3)])
это не значит, что это препятствие, которое представляет собой такое представление: поскольку это представление может использоваться для создания идентичного упорядоченного OrderedDict
.
Только для полноты (уже упоминалось) порядок теряется, потому что OrderedDict(a=1, b=2, c=3)
ловит эти аргументы как **kwargs
, что является нормальным неупорядоченным dict
. По крайней мере, пока python 3.6 не пришел и не выполнил обещание, что порядок kwargs
будет сохранен, когда вы передадите его так же, как и вы:
Что нового в Python 3.6
PEP 468: Сохранение порядка аргументов ключевого слова
**kwargs
в сигнатуре функции теперь гарантируется сохранение в порядке сохранения порядка.
Ответ 3
Прочитайте документы:
Конструктор OrderedDict и метод update() принимают аргументы ключевого слова, но их порядок теряется, поскольку функция Pythons вызывает семантические аргументы аргументов pass-in с использованием обычного неупорядоченного словаря.
Вы должны передать ввод как последовательность кортежей (или существующий тип упорядоченного дикта), чтобы сохранить порядок.
Ответ 4
Это потому, что аргументы ключевого слова (variable = value, )
, которые вы передаете, сначала будут объединены в словарь Python. И словари Python неупорядочены. kwds
будет этот словарь, как вы можете видеть в сигнатуре Init.
Init signature: OrderedDict(self, *args, **kwds)
Вот как OrderedDict будет инициализироваться внутри, когда вы передадите аргументы ключевого слова:
for key, value in kwds.items():
self[key] = value
Так как kwds
неупорядочен, вы получите неупорядоченный OrderedDict.
Вы можете создать упорядоченный dict так:
from collections import OrderedDict
from string import ascii_lowercase
d = OrderedDict()
for a,b in enumerate(ascii_lowercase[:3], 1):
d[b] = a
Или:
n=3
d = OrderedDict(zip(ascii_lowercase[:n], range(1,n+1)))
print d
Вывод:
OrderedDict([('a', 1), ('b', 2), ('c', 3)])
Ответ 5
Вы можете создать нужное отображение, используя sorted()
:
dict = {"a":"some_value", "b":"other_value", "c":"foo"}
ordered = OrderedDict(sorted(dict.items(), key=lambda t: t[0]))
Это сортирует элементы перед передачей их конструктору OrderedDict
.
Раздел key=
устанавливает сортировку, а t[0]
сортирует ключ словаря.