Перетворення дикта в OrdersDict


138

У мене є проблеми з використанням collections.OrderedDictкласу. Я використовую Python 2.7 на Raspbian, дистрибутив Debian для Raspberry Pi. Я намагаюся надрукувати два словники, щоб порівняти (поруч) текстову пригоду. Порядок є важливим для точного порівняння. Незалежно від того, що я намагаюся надрукувати словники в їх звичайному не упорядкованому вигляді.

Ось що я отримую, коли це роблю на своєму RPi:

import collections

ship = {"NAME": "Albatross",
         "HP":50,
         "BLASTERS":13,
         "THRUSTERS":18,
         "PRICE":250}

ship = collections.OrderedDict(ship)

print ship
# OrderedDict([('PRICE', 250), ('HP', 50), ('NAME', 'Albatross'), ('BLASTERS', 13), ('THRUSTERS', 18)])

Очевидно, що щось не вірно, тому що він друкує виклик функції та ставить ключі та групи значень у вкладений список ...

Ось що я отримав, запустивши щось подібне на своєму ПК:

import collections

Joe = {"Age": 28, "Race": "Latino", "Job": "Nurse"}
Bob = {"Age": 25, "Race": "White", "Job": "Mechanic", "Random": "stuff"}

#Just for clarity:
Joe = collections.OrderedDict(Joe)
Bob = collections.OrderedDict(Bob)

print Joe
# OrderedDict([('Age', 28), ('Race', 'Latino'), ('Job', 'Nurse')])
print Bob
# OrderedDict([('Age', 25), ('Race', 'White'), ('Job', 'Mechanic'), ('Random', 'stuff')])

Цього разу це в порядку, але не слід друкувати інші речі, хоча так? (Внесення його до списку та показ виклику функції.)

Де я роблю свою помилку? Це не повинно бути нічого спільного з пі-версією Python, оскільки це лише версія Linux.


3
Примітка: OrderedDictсортується за порядком вставки, а не буквено-цифровим порядком ключів.
el.pescado

Відповіді:


214

Спочатку ви створюєте словник , а потім передаєте цей словник an OrderedDict. Для версій Python <3.6 (*) до цього часу впорядкування вже не буде правильним. dictпо своїй суті не впорядковано.

Замість цього передайте послідовність кортежів:

ship = [("NAME", "Albatross"),
        ("HP", 50),
        ("BLASTERS", 13),
        ("THRUSTERS", 18),
        ("PRICE", 250)]
ship = collections.OrderedDict(ship)

Те, що ви бачите під час друку, OrderedDict- це представлення , і це цілком правильно. OrderedDict([('PRICE', 250), ('HP', 50), ('NAME', 'Albatross'), ('BLASTERS', 13), ('THRUSTERS', 18)])у зображенні, що відтворюється , просто показує , який вміст містить OrderedDict.


(*) : У реалізації CPython 3.6 dictтип було оновлено для використання більш ефективної пам'яті внутрішньої структури, яка має щасливий побічний ефект від збереження порядку вставки, а за допомогою розширення код, показаний у питанні, працює без проблем. Станом на Python 3.7, специфікація мови Python була оновлена, щоб вимагати, щоб усі реалізації Python дотримувалися цієї поведінки. Докладні відомості див. У цій іншій моїй відповіді, а також чому ви все-таки можете скористатися OrderedDict()певним випадком.


Добре, що OrdersDict СТВОРИТИ словник для мене? Крім того, для друку без відтворюваного представлення чи можу я просто надрукувати змінну OrdersDict, в якій використовується? тобто: print ship ?? Дякую :)
pythonpiboy

3
Питання: У описаному вами порядку OrdersDict складає упорядкований "список". Хіба це не перемагає мети? Він створює лише список елементів, а не словники з ключами та значеннями ...
pythonpiboy

9
Тип діє як обидва; відображення, що зберігає порядок. Щоб створити його з замовленням, потрібно навести його в порядку . Оскільки стандартний дикт (на чому-небудь крім PyPI або Python 3.6+) не може цього зробити, ви надаєте йому список кортежів. Після того , як OrderedDictбуде створено він є словником.
Martijn Pieters

4
Здається, що плутанина - це припущення, що OrdersDict "застосовує" замовлення, а не просто збереження замовлення. Я, звичайно, припускав, що це буде сортувати вхід при створенні - або що функція items () повертає відсортовані елементи незалежно від того, коли вони були вставлені. Натомість він просто зберігає будь-яке замовлення, яке ви надаєте.
whiterook6

2
@ whiterook6: це не відсортований словник. Це впорядкований словник, словник, який записує порядок пар ключів і значень і дає змогу повторно замовляти ці пари. Порівняйте це зі списками, впорядкованими послідовностями .
Martijn Pieters

36

Якщо ви не можете редагувати цю частину коду, де був визначений ваш дікт, ви все одно можете замовити його в будь-якому місці будь-яким способом, як вам потрібно:

from collections import OrderedDict

order_of_keys = ["key1", "key2", "key3", "key4", "key5"]
list_of_tuples = [(key, your_dict[key]) for key in order_of_keys]
your_dict = OrderedDict(list_of_tuples)

11

Більшу частину часу ми їдемо за OrdersDict, коли нам потрібен спеціальний замовлення, а не загальний, як ASC тощо.

Ось запропоноване рішення:

import collections
ship = {"NAME": "Albatross",
         "HP":50,
         "BLASTERS":13,
         "THRUSTERS":18,
         "PRICE":250}

ship = collections.OrderedDict(ship)

print ship


new_dict = collections.OrderedDict()
new_dict["NAME"]=ship["NAME"]
new_dict["HP"]=ship["HP"]
new_dict["BLASTERS"]=ship["BLASTERS"]
new_dict["THRUSTERS"]=ship["THRUSTERS"]
new_dict["PRICE"]=ship["PRICE"]


print new_dict

Це буде результатом:

OrderedDict([('PRICE', 250), ('HP', 50), ('NAME', 'Albatross'), ('BLASTERS', 13), ('THRUSTERS', 18)])
OrderedDict([('NAME', 'Albatross'), ('HP', 50), ('BLASTERS', 13), ('THRUSTERS', 18), ('PRICE', 250)])

Примітка . Нові відсортовані словники підтримують свій порядок сортування, коли записи видаляються. Але коли додаються нові ключі, вони додаються до кінця, і сортування не підтримується. ( Офіційний документ )


2

Використовуйте dict.items (); це може бути так само просто, як наступне:

ship = collections.OrderedDict(ship.items())
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.