Упорядоченный номер не заказан?

Я пытаюсь использовать 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)])

Как я могу убедиться, что он создан в правильном порядке, который я намерен?

+23
источник поделиться
5 ответов

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 диктует, что собранные аргументы ключевого слова будут отображаться в теле функции как упорядоченное сопоставление.

+46
источник

Странно, что он уже не упоминался, но представление 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 в сигнатуре функции теперь гарантируется сохранение в порядке сохранения порядка.

+18
источник

Прочитайте документы:

Конструктор OrderedDict и метод update() принимают аргументы ключевого слова, но их порядок теряется, поскольку функция Pythons вызывает семантические аргументы аргументов pass-in с использованием обычного неупорядоченного словаря.

Вы должны передать ввод как последовательность кортежей (или существующий тип упорядоченного дикта), чтобы сохранить порядок.

+12
источник

Это потому, что аргументы ключевого слова (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)])
+3
источник

Вы можете создать нужное отображение, используя sorted():

dict = {"a":"some_value", "b":"other_value", "c":"foo"}
ordered = OrderedDict(sorted(dict.items(), key=lambda t: t[0]))

Это сортирует элементы перед передачей их конструктору OrderedDict.

Раздел key= устанавливает сортировку, а t[0] сортирует ключ словаря.

0
источник

Посмотрите другие вопросы по меткам или Задайте вопрос