2013-07-16 27 views
13

Sto provando a ripetere un dizionario che ho definito in un ordine specifico, ma itera sempre in un ordine diverso da quello che ho definito nel mio codice. Questo è solo un esempio di base di ciò che sto cercando di fare. Il dizionario su cui sto andando a scorrere è molto più grande, ha chiavi con un nome molto più complesso e non è in ordine alfabetico/numerico.Come eseguire iterazioni su un dizionario Python in ordine definito?

level_lookup = \ 
{ 
'PRIORITY_1' : { 'level' : 'BAD', 'value' : '' }, 
'PRIORITY_2' : { 'level' : 'BAD', 'value' : '' }, 
'PRIORITY_3' : { 'level' : 'BAD', 'value' : '' }, 
'PRIORITY_4' : { 'level' : 'BAD', 'value' : '' }, 
'PRIORITY_5' : { 'level' : 'CHECK', 'value' : '' }, 
'PRIORITY_6' : { 'level' : 'CHECK', 'value' : '' }, 
'PRIORITY_7' : { 'level' : 'GOOD', 'value' : '' }, 
'PRIORITY_8' : { 'level' : 'GOOD', 'value' : '' }, 
} 

for priority in level_lookup: 
    if(level_lookup[ priority ][ 'value' ] == 'TRUE'): 
     set_levels += str(priority) + '\n' 

Ho bisogno dell'ordine in cui definisco il dizionario da conservare durante l'iterazione. Il mio ordine non è alfabetico, quindi ordinare in ordine alfabetico non sarebbe di grande aiuto. C'è un modo per fare questo? Ho provato `level_lookup.items(), ma non mantiene il mio ordine.

+1

Se si desidera utilizzare un normale dizionario in un ordine particolare. .. [non farlo] (http://blog.amir.rachum.com/post/54458435089/python-hash-id-and-dictionary-order). Usa invece un 'OrderedDict'. – KronoS

+5

I dizionari non hanno un ordine.Cioè, gli oggetti devono venire fuori in un certo ordine quando si itera, ma è tutto ciò che è più semplice per Python, e potrebbe o non assomigliare all'ordine in cui sono stati inseriti gli oggetti, e potrebbe cambiare quando si aggiungono o si eliminano elementi. Se vuoi i tuoi articoli in un ordine, usa un contenitore che mantiene l'ordine dell'articolo, come ad esempio 'collections.OrderedDict'. – kindall

risposta

9

È necessario utilizzare uno OrderedDict. Funziona esattamente come lo si desidera, tuttavia è necessario definirlo in questo modo. In alternativa, è possibile avere un elenco di chiavi in ​​ordine e scorrere l'elenco e accedere al dizionario. Qualcosa a lunghe le linee di:

level_lookup_order = ['PRIORITY_1', 'PRIORITY_2', ...] 
for key in level_lookup_order: 
    if key in level_lookup: 
     do_stuff(level_lookup[key]) 

Questo sarà un dolore per mantenere, però, quindi vi consiglio di usare solo l'OrderedDict.

Come ultima opzione, è possibile utilizzare le 'costanti'. Come,

PRIORITY_1 = 1 
PRIORITY_2 = 2 
... 
lookup_order = {PRIORITY_1: 42, PRIORITY_2: 24, ...} 
+1

OrderedDict ha fatto il trucco perfettamente. Grazie! – PseudoPsyche

4

utilizzare collections.OrderedDict. Se questo non funziona per voi, è possibile ordinare le chiavi prima di eseguire iterazioni su di loro:

for k in sorted(myDict, lambda k: int(k.rsplit("_",1)[1]): 
    # do stuff 

Nota tuttavia, che questo particolare ordinamento costa spazio lineare e O tempo (nlogn). Inoltre, utilizza il sistema di numerazione coincidente "PRIORITY_N" per l'ordinamento, che potrebbe non essere sempre valido

2

Prova;

for priority in sorted(level_lookup.iterkeys()): 

Come Jon ha sottolineato, keys() e iterkeys() sono ridondanti qui;

for priority in sorted(level_lookup): 
+2

'iterkeys()' etc ... è ridondante qui ... basta usare 'ordinato (level_lookup)' - funzionerà per Python 2 e 3 –

+0

Così fa! Grazie! –

+0

Bella risposta. Non so perché questa non era la risposta "corretta" preferita. –

6

Se stai bene con utilizzando l'ordine chiave-ordinato:

for key in sorted(level_lookup.keys()): 
    ... 

Questo è quello che in genere faccio se il dict viene fornito per me, e non qualcosa che un'istanza di (piuttosto che OrderedDict.

0

penso che si sarebbe meglio non usando un dizionario containg e vedere alcuna ragione per usare uno in questo caso. Un list sarebbe memorizzare gli elementi nell'ordine desiderato:

level_lookup = [ 
    {'level': 'BAD', 'value': '' }, 
    {'level': 'BAD', 'value': '' }, 
    {'level': 'BAD', 'value': '' }, 
    {'level': 'BAD', 'value': '' }, 
    {'level': 'CHECK', 'value': 'TRUE'}, 
    {'level': 'CHECK', 'value': 'TRUE'}, 
    {'level': 'GOOD', 'value': '' }, 
    {'level': 'GOOD', 'value': '' }, 
] 

set_levels = '' 
for level, priority in enumerate(level_lookup, start=1): 
    if priority['value'] == 'TRUE': 
     set_levels += 'PRIORITY_{!s}\n'.format(level) 
print set_levels 

In realtà, si potrebbe scrivere il tutto come lista di comprensione:

set_levels = ('\n'.join('PRIORITY_{!s}'.format(level) 
       for level, priority in enumerate(level_lookup, start=1) 
        if priority['value'] == 'TRUE')) 
print set_levels 
+0

Funzionerebbe, ma ci sono altre sezioni di codice che dipendono dal fare ricerche di dizionario basate sulle chiavi. Potrei scorrere un elenco, ma è più pulito mantenere questo modo piuttosto che scorrere un elenco molto grande ogni volta che stai cercando qualcosa quando la chiave è nota. – PseudoPsyche

Problemi correlati