Правильний спосіб ініціалізації OrdersDict за допомогою його конструктора таким чином, щоб він зберігав порядок початкових даних?


124

Який правильний спосіб ініціалізувати впорядкований словник (OD), щоб він зберігав порядок початкових даних?

from collections import OrderedDict

# Obviously wrong because regular dict loses order
d = OrderedDict({'b':2, 'a':1}) 

# An OD is represented by a list of tuples, so would this work?
d = OrderedDict([('b',2), ('a', 1)])

# What about using a list comprehension, will 'd' preserve the order of 'l'
l = ['b', 'a', 'c', 'aa']
d = OrderedDict([(i,i) for i in l])

Питання:

  • Чи буде OrderedDictзбережений порядок списку кортежів, або кортеж кортежів, кортеж списків або список списків тощо, переданих під час ініціалізації (2-й та 3-й приклад вище)?

  • Як можна перевірити, чи OrderedDictдійсно підтримує замовлення? Оскільки a dictмає непередбачуваний порядок, що робити, якщо на щастя мої тестові вектори мають такий же початковий порядок, що і непередбачуваний порядок диктату? Наприклад, якщо замість того, d = OrderedDict({'b':2, 'a':1})щоб писати d = OrderedDict({'a':1, 'b':2}), я можу помилково зробити висновок про збереження порядку. У цьому випадку я з’ясував, що a dictвпорядковується в алфавітному порядку, але це може бути не завжди правдою. Що є надійним способом використання контрприкладу, щоб перевірити, чи зберігає структура даних порядок чи ні, окрім спроб тестування векторів повторно, поки один не зламається?

PS Я просто залиште це для посилання : "Конструктор OrdersDict та update () метод приймають аргументи ключових слів, але їх порядок втрачається, оскільки семантика виклику функції Python передає аргументи ключових слів, використовуючи звичайний не упорядкований словник".

PPS: Сподіваємось, в майбутньому OrdersDict збереже також порядок kwargs (приклад 1): http://bugs.python.org/issue16991


10
Нечітко іронічно, що ініціалізувати OrdersDict (не порожній) дикт - це неправильно робити ... можливо, це повинно призвести до попередження, оскільки це, ймовірно, порушує наміри користувача.
smci

3
Після python3.6, OrderDict(b=2, a=1)також є правильним способом. Див. PEP 468 .
ІванаГиро

Відповіді:


90

OrdersDict збереже будь-який порядок, до якого він має доступ. Єдиний спосіб передавати впорядковані дані для його ініціалізації - це передати список (або, загалом, ітерабельний) пар ключових значень, як у двох останніх прикладах. Як зазначається в документації, з якою ви посилаєтесь, OrdersDict не має доступу до жодного замовлення під час передачі аргументів ключових слів або аргументу dict, оскільки будь-яке замовлення там видаляється до того, як його побачить конструктор OrdersDict.

Зауважте, що використання розуміння списку в останньому прикладі нічого не змінює. Ніякої різниці між OrderedDict([(i,i) for i in l])і OrderedDict([('b', 'b'), ('a', 'a'), ('c', 'c'), ('aa', 'aa')]). Зрозуміння списку оцінюється і створює список, і він передається; OrriedDict нічого не знає про те, як він був створений.


74
# An OD is represented by a list of tuples, so would this work?
d = OrderedDict([('b', 2), ('a', 1)])

Так, це спрацює. За визначенням, список завжди упорядковується так, як він представлений. Це стосується і розуміння списку, згенерований список аналогічно наданим даним (тобто джерело зі списку буде детермінованим, отриманим із setчи dictне дуже багато).

Як можна перевірити, чи OrderedDictдійсно підтримує замовлення. Оскільки дикт має непередбачуваний порядок, що робити, якщо мої вектори тестів, на щастя, мають такий же початковий порядок, що і непередбачуваний порядок дикта? Наприклад, якщо замість того, d = OrderedDict({'b':2, 'a':1})щоб писати d = OrderedDict({'a':1, 'b':2}), я можу помилково зробити висновок про збереження порядку. У цьому випадку я з’ясував, що a dictє впорядкованим за алфавітом, але це може бути не завжди правдою. тобто який надійний спосіб використовувати приклад лічильника, щоб перевірити, чи структура даних зберігає порядок чи не вистачає повторних спроб тестових векторів до тих пір, поки один не перерветься.

Ви зберігаєте свій вихідний список з 2-ма пакетами навколо для довідки та використовуєте їх як свої тестові дані для своїх тестових випадків, коли ви робите одиничні тести. Перегляньте їх і забезпечте підтримання порядку.


Про підтвердження порядку: Як я можу переконатися, що мій 2-кортевий порушить порядок дікта, якщо це непередбачувано? Це загальне запитання про будь-яку структуру даних, можливо, я мушу розділити її з цього питання.
натисніть

1
Ви не можете детерміновано зламати щось, що не є детермінованим за своєю суттю.
метатостер

1
То який правильний підхід до тестування таких речей? Ви просто продовжуєте намагатися нескінченно? Порядок є непередбачуваним для програмістів, але оскільки це хеш-карта, слід дотримуватися алгоритму "якийсь" і правильний тест повинен намагатися протидіяти цьому?
натисніть

2
Див __hash__. Зокрема про strтип.
метатостер

За визначенням, список завжди упорядковується так, як він представлений. Це було ключовим твердженням для мене. Я вирішив просто використати список 2-кортезів для свого основного, OrderedDictщоб у мене не було накладних витрат на перетворення списку в an OrderedDict. Я просто перебираю елементи, такі як список, а не словник.
Бобборт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.