Modo giusto per inizializzare un OrderedDict utilizzando il suo costruttore in modo tale che mantenga l'ordine dei dati iniziali?


124

Qual è il modo corretto per inizializzare un dizionario ordinato (OD) in modo che mantenga l'ordine dei dati iniziali?

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

Domanda:

  • Sarà un OrderedDictpreservare l'ordine di una lista di tuple o tuple di tuple o tuple di liste o lista di liste, ecc passato al momento della inizializzazione (2 ° e 3 ° esempio di cui sopra)?

  • Come si verifica se OrderedDicteffettivamente mantiene un ordine? Dato che a dictha un ordine imprevedibile, cosa succede se i miei vettori di test hanno fortunatamente lo stesso ordine iniziale dell'ordine imprevedibile di un dict? Ad esempio, se invece di d = OrderedDict({'b':2, 'a':1})scrivere d = OrderedDict({'a':1, 'b':2}), posso erroneamente concludere che l'ordine è conservato. In questo caso, ho scoperto che a dictè ordinato alfabeticamente, ma potrebbe non essere sempre vero. Qual è un modo affidabile per utilizzare un controesempio per verificare se una struttura dati conserva l'ordine o meno, a meno di provare ripetutamente i vettori di prova fino a quando non si rompe?

PS Lo lascio qui solo come riferimento : "Il costruttore OrderedDict e il metodo update () accettano entrambi gli argomenti delle parole chiave, ma il loro ordine è perso perché la semantica della chiamata di funzione di Python passa gli argomenti delle parole chiave usando un normale dizionario non ordinato"

PPS: Si spera che in futuro OrderedDict conserverà anche l'ordine di kwargs (esempio 1): http://bugs.python.org/issue16991


10
È vagamente ironico che inizializzare un OrderedDict con un dict (non vuoto) sia la cosa sbagliata da fare ... probabilmente ciò dovrebbe risultare in un avviso poiché probabilmente viola l'intento dell'utente.
smci

3
Dopo python3.6, OrderDict(b=2, a=1)è anche un modo corretto. Vedere PEP 468 .
IvanaGyro

Risposte:


90

OrderedDict conserverà qualsiasi ordine a cui ha accesso. L'unico modo per passargli i dati ordinati per l'inizializzazione è passare un elenco (o, più in generale, un iterabile) di coppie chiave-valore, come negli ultimi due esempi. Come dice la documentazione a cui ti sei collegato, OrderedDict non ha accesso a nessun ordine quando passi argomenti di parole chiave o un argomento dict, poiché qualsiasi ordine lì viene rimosso prima che il costruttore di OrderedDict lo veda.

Nota che l'utilizzo di una comprensione dell'elenco nel tuo ultimo esempio non cambia nulla. Non c'è differenza tra OrderedDict([(i,i) for i in l])e OrderedDict([('b', 'b'), ('a', 'a'), ('c', 'c'), ('aa', 'aa')]). La comprensione della lista viene valutata e crea la lista e viene passata; OrderedDict non sa come è stato creato.


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

Sì, funzionerà. Per definizione, un elenco è sempre ordinato nel modo in cui è rappresentato. Questo vale anche per la comprensione della lista, la lista generata è nello stesso modo in cui i dati sono stati forniti (cioè la fonte da una lista sarà deterministica, proveniente da una seto dictnon così tanto).

Come si verifica se OrderedDicteffettivamente mantiene un ordine. Dato che un dict ha un ordine imprevedibile, cosa succede se i miei vettori di test hanno fortunatamente lo stesso ordine iniziale dell'ordine imprevedibile di un dict ?. Ad esempio, se invece di d = OrderedDict({'b':2, 'a':1})scrivere d = OrderedDict({'a':1, 'b':2}), posso erroneamente concludere che l'ordine è conservato. In questo caso, ho scoperto che a dictè in ordine alfabetico, ma potrebbe non essere sempre vero. vale a dire qual è un modo affidabile per utilizzare un esempio di contatore per verificare se una struttura dati conserva l'ordine o non a meno di provare ripetutamente i vettori di prova fino a quando uno si rompe.

Mantieni il tuo elenco di sorgenti di 2 tuple in giro per riferimento e lo usi come dati di test per i tuoi casi di test quando esegui i test unitari. Scorri attraverso di essi e assicurati che l'ordine venga mantenuto.


Informazioni sulla verifica dell'ordine: come posso assicurarmi che la mia tupla a 2 interromperà l'ordine di dict se è imprevedibile? Questa è una domanda generica su qualsiasi struttura dati, forse dovrei separarla da questa domanda.
fare clic su

1
Non puoi rompere deterministicamente qualcosa di natura non deterministica.
metatoaster

1
Allora qual è l'approccio giusto per testare queste cose? Continui a provare indefinitamente? L'ordine è imprevedibile per i programmatori, ma poiché è una mappa hash, segue un algoritmo "un po '" e un test corretto dovrebbe provare a contrastarlo?
fare clic su

2
Vedi __hash__. In particolare sul strtipo.
metatoaster

Per definizione, un elenco è sempre ordinato nel modo in cui è rappresentato. Questa è stata una dichiarazione chiave per me. Ho deciso di utilizzare semplicemente un elenco di 2 tuple per il mio basic in OrderedDictmodo da non dover convertire un elenco in un file OrderedDict. Mi limito a scorrere gli elementi come un elenco invece di un dizionario.
Bobort
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.