Как перебирать словарь Python в определенном порядке? - программирование

Как перебирать словарь Python в определенном порядке?

Я пытаюсь перебрать словарь, который я определил в определенном порядке, но он всегда выполняет итерацию в другом порядке, чем то, что я определил в своем коде. Это всего лишь базовый пример того, что я пытаюсь сделать. Словарь, который я перебираю, намного больше, имеет гораздо более сложные имена и не находится в алфавитном/цифровом порядке.

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'

Мне нужен порядок, в котором я определяю словарь для сохранения во время итерации. Мой заказ не в алфавитном порядке, поэтому сортировка в алфавитном порядке не помогла бы. Есть какой-либо способ сделать это? Я попробовал `level_lookup.items(), но это тоже не поддерживает мой заказ.

4b9b3361

Ответ 1

Вы должны использовать OrderedDict. Он работает именно так, как вы хотите, но вам нужно определить его таким образом. Кроме того, вы можете иметь список ключей по порядку, а также перебирать список и доступ к словарю. Что-то вроде:

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

Это будет болью для поддержания, тем не менее, поэтому я рекомендую вам просто использовать OrderedDict.

В качестве последнего варианта вы можете использовать "константы". Как,

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

Ответ 2

Если вам будет удобно использовать отсортированный по ключам порядок:

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

То, что я обычно делаю, если мне предоставляется dict, а не что-то, что я создаю (вместо OrderedDict.

Ответ 3

Вы можете использовать collections.OrderedDict. Если это не сработает для вас, вы можете сортировать ключи до того, как вы их перейдете:

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

Обратите внимание, однако, что эта конкретная сортировка стоит линейное пространство и время O (nlogn). Кроме того, для сортировки используется совпадающая система нумерации "PRIORITY_N", которая не всегда может быть действительной

Ответ 4

Попробуйте

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

Как указал Джон, keys() и iterkeys() здесь избыточны;

for priority in sorted(level_lookup):

Ответ 5

Я думаю, вам было бы лучше не использовать словарь-созерцатель и не видеть никаких веских причин использовать его в этом случае. A list сохранит элементы в нужном порядке:

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

Фактически, вы могли бы написать все это как понимание списка:

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