Konwertowanie dict na OrderedDict


138

Mam problemy z używaniem tej collections.OrderedDictklasy. Używam Pythona 2.7 na Raspbian, dystrybucji Debiana dla Raspberry Pi. Próbuję wydrukować dwa słowniki w celu porównania (obok siebie) do przygody z tekstem. Kolejność jest niezbędna do dokładnego porównania. Bez względu na to, czego próbuję, słowniki drukują w zwykły, nieuporządkowany sposób.

Oto, co otrzymuję, robiąc to na moim 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)])

Oczywiście coś jest nie tak, ponieważ wypisuje wywołanie funkcji i umieszcza klucze i grupy wartości w zagnieżdżonej liście ...

Oto, co otrzymałem, uruchamiając coś podobnego na moim komputerze:

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')])

Tym razem jest w porządku, ale nie powinno się drukować innych rzeczy, prawda? (Umieszczenie go na liście i pokazanie wywołania funkcji.)

Gdzie popełniam błąd? Nie powinno to mieć nic wspólnego z wersją pi Pythona, ponieważ jest to tylko wersja dla Linuksa.


3
Uwaga: OrderedDictjest sortowany według kolejności reklamowej, a nie alfanumerycznej kolejności kluczy.
el.pescado

Odpowiedzi:


214

Najpierw tworzysz słownik , a następnie przekazujesz go do pliku OrderedDict. W przypadku wersji Pythona <3.6 (*) , do czasu gdy to zrobisz, kolejność nie będzie już poprawna. dictz natury nie jest uporządkowany.

Zamiast tego podaj sekwencję krotek:

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

To, co widzisz, gdy drukujesz, OrderedDictjest jego reprezentacją i jest całkowicie poprawne. OrderedDict([('PRICE', 250), ('HP', 50), ('NAME', 'Albatross'), ('BLASTERS', 13), ('THRUSTERS', 18)])po prostu pokazuje, w możliwej do odtworzenia reprezentacji, jaka jest zawartość pliku OrderedDict.


(*) : W implementacji CPython 3.6, dicttyp został zaktualizowany, aby używać bardziej wydajnej pamięci wewnętrznej struktury, która ma szczęśliwy efekt uboczny w postaci zachowania kolejności wstawiania, a przez rozszerzenie kod pokazany w pytaniu działa bez problemów. Od wersji Python 3.7 specyfikacja języka Python została zaktualizowana, aby wymagać, aby wszystkie implementacje Pythona były zgodne z tym zachowaniem. Zobacz tę inną moją odpowiedź, aby uzyskać szczegółowe informacje, a także dlaczego nadal możesz chcieć użyć OrderedDict()w niektórych przypadkach.


Ok, więc OrderedDict utworzy dla mnie słownik? Ponadto, aby wydrukować bez odtwarzalnej reprezentacji, czy mogę po prostu wydrukować zmienną OrderedDict, w której jest używana? tj .: print ship ?? Dzięki :)
pythonpiboy

3
Pytanie: W sposób, który opisałeś, OrderedDict tworzy uporządkowaną „listę”. Czy to nie pokonuje celu? Tworzy tylko listę elementów, a nie słowniki z kluczami i wartościami ...
pythonpiboy

9
Typ działa jak oba; mapowanie, które zachowuje porządek. Aby utworzyć jedną z zamawiania, trzeba dać mu elementy w kolejności . Ponieważ standardowe dyktowanie (na czymkolwiek innym niż PyPI lub Python 3.6+) nie może tego zrobić, zamiast tego podajesz mu listę krotek. Gdy OrderedDictjest tworzona to jest słownik.
Martijn Pieters

4
Wygląda na to, że zamieszanie wynika z założenia, że ​​OrderedDict „stosuje” polecenie, a nie tylko je zachowuje. Z pewnością założyłem, że posortuje dane wejściowe podczas tworzenia - lub że funkcja items () zwróci posortowane elementy niezależnie od tego, kiedy zostały wstawione. Zamiast tego po prostu zachowuje to, co podasz.
whiterook6

2
@ whiterook6: to nie jest posortowany słownik nr. Jest to słownik uporządkowany, słownik, który rejestruje kolejność par klucz-wartość i umożliwia zmianę kolejności tych par. Porównaj to z listami, które są uporządkowanymi sekwencjami .
Martijn Pieters

36

Jeśli nie możesz edytować tej części kodu, w której zdefiniowano twój dykt, nadal możesz go zamówić w dowolnym momencie w dowolny sposób, na przykład:

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

Przez większość czasu korzystamy z OrderedDict, gdy wymagaliśmy niestandardowego zamówienia, a nie ogólnego, takiego jak ASC itp.

Oto proponowane rozwiązanie:

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

To wyświetli:

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

Uwaga : Nowe posortowane słowniki zachowują porządek sortowania po usunięciu wpisów. Ale kiedy dodawane są nowe klucze, są one dołączane na końcu, a sortowanie nie jest utrzymywane. ( Oficjalny dokument )


2

Użyj dict.items (); może to być tak proste, jak:

ship = collections.OrderedDict(ship.items())
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.