Właściwy sposób na zainicjowanie OrderedDict przy użyciu jego konstruktora, tak aby zachował kolejność danych początkowych?

124

Jaki jest prawidłowy sposób zainicjowania uporządkowanego słownika (OD), aby zachował kolejność danych początkowych?

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

Pytanie:

  • Czy OrderedDictzachowa kolejność listy krotek, krotek krotek lub krotek list lub list list itp. Przekazanych w czasie inicjalizacji (przykład 2 i 3 powyżej)?

  • Jak sprawdzić, czy OrderedDictfaktycznie utrzymuje zamówienie? Ponieważ dictkolejność a ma nieprzewidywalną kolejność, co się stanie, jeśli moje wektory testowe na szczęście mają tę samą początkową kolejność, co nieprzewidywalna kolejność dyktu? Na przykład, jeśli zamiast d = OrderedDict({'b':2, 'a':1})pisać d = OrderedDict({'a':1, 'b':2}), mogę błędnie stwierdzić, że porządek jest zachowany. W tym przypadku dowiedziałem się, że a dictjest uporządkowane alfabetycznie, ale nie zawsze może to być prawda. Jaki jest niezawodny sposób wykorzystania kontrprzykładu do sprawdzenia, czy struktura danych zachowuje porządek, czy nie, oprócz wielokrotnego wypróbowywania wektorów testowych, aż jeden się zepsuje?

PS Zostawię to tutaj jako odniesienie : "Konstruktor OrderedDict i metoda update () akceptują argumenty słów kluczowych, ale ich kolejność jest tracona, ponieważ semantyka wywołań funkcji Pythona argumenty słów kluczowych pass-in przy użyciu zwykłego słownika nieuporządkowanego"

PPS: Miejmy nadzieję, że w przyszłości OrderedDict również zachowa kolejność kwargów (przykład 1): http://bugs.python.org/issue16991

Kliknij
źródło
10
To trochę ironiczne, że zainicjowanie OrderedDict z (niepustym) dyktem jest niewłaściwą rzeczą do zrobienia ... prawdopodobnie powinno to spowodować ostrzeżenie, ponieważ prawdopodobnie narusza intencje użytkownika.
smci
3
Po pythonie3.6 OrderDict(b=2, a=1)jest też właściwy sposób. Zobacz PEP 468 .
IvanaGyro

Odpowiedzi:

90

OrderedDict zachowa każde zamówienie, do którego ma dostęp. Jedynym sposobem przekazania do niego uporządkowanych danych w celu zainicjowania jest przekazanie listy (lub, bardziej ogólnie, iterowalnej) par klucz-wartość, tak jak w dwóch ostatnich przykładach. Jak mówi dokumentacja, z którą się łączysz, OrderedDict nie ma dostępu do żadnej kolejności, gdy przekazujesz argumenty słów kluczowych lub argumenty dict, ponieważ każda kolejność jest usuwana, zanim konstruktor OrderedDict je zobaczy.

Zwróć uwagę, że użycie list składanych w ostatnim przykładzie niczego nie zmienia. Nie ma różnicy między OrderedDict([(i,i) for i in l])i OrderedDict([('b', 'b'), ('a', 'a'), ('c', 'c'), ('aa', 'aa')]). Zrozumienie listy jest oceniane, tworzy listę i jest przekazywana; OrderedDict nic nie wie o tym, jak został stworzony.

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

Tak, to zadziała. Z definicji lista jest zawsze uporządkowana tak, jak jest reprezentowana. Odnosi się to również do rozumienia list, generowana lista jest w ten sam sposób, w jaki dane zostały dostarczone (tj. Źródło z listy będzie deterministyczne, pochodzi z setlub dictnie).

Jak można sprawdzić, czy OrderedDictfaktycznie utrzymuje zamówienie. Ponieważ dykt ma nieprzewidywalną kolejność, co się stanie, jeśli moje wektory testowe na szczęście mają tę samą początkową kolejność, co nieprzewidywalna kolejność dyktowania? Na przykład, jeśli zamiast d = OrderedDict({'b':2, 'a':1})pisać d = OrderedDict({'a':1, 'b':2}), mogę błędnie stwierdzić, że porządek jest zachowany. W tym przypadku dowiedziałem się, że a dictto kolejność alfabetyczna, ale nie zawsze może to być prawda. tj. jaki jest niezawodny sposób wykorzystania kontrprzykładu do sprawdzenia, czy struktura danych zachowuje porządek, czy nie jest pozbawiona możliwości wielokrotnego wypróbowywania wektorów testowych, aż jeden z nich się zepsuje.

Przechowujesz listę źródłową 2-krotek w celach informacyjnych i używasz jej jako danych testowych dla przypadków testowych podczas wykonywania testów jednostkowych. Powtarzaj je i upewnij się, że została zachowana kolejność.

metatoaster
źródło
O weryfikacji zamówienia: Jak się upewnić, że moja 2 krotka ZŁAMANIE kolejności dyktowania, jeśli jest nieprzewidywalna? To jest ogólne pytanie dotyczące dowolnej struktury danych, być może powinienem oddzielić je od tego pytania.
kliknij
1
Nie można deterministycznie złamać czegoś, co nie jest z natury deterministyczne.
metatoaster
1
Jakie jest więc właściwe podejście do testowania takich rzeczy? Po prostu próbujesz w nieskończoność? Kolejność jest nieprzewidywalna dla programistów, ale ponieważ jest to mapa mieszająca, jest zgodna z „jakimś” algorytmem i odpowiedni test powinien spróbować temu przeciwdziałać?
kliknij
2
Zobacz __hash__. W szczególności o strtypie.
metatoaster
Z definicji lista jest zawsze uporządkowana tak, jak jest reprezentowana. To było dla mnie kluczowe stwierdzenie. Postanowiłem po prostu użyć listy 2-krotek do mojego podstawowego, OrderedDictaby nie musieć narzutu konwersji listy na plik OrderedDict. Po prostu przeglądam elementy, takie jak lista zamiast słownika.
Bobort