Как перебирать словарь 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(), но это тоже не поддерживает мой заказ.
Ответы
Ответ 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