简体   繁体   English

如何按定义的顺序迭代Python字典?

[英]How to iterate over a Python dictionary in defined order?

I'm trying to iterate over a dictionary that I have defined in a specific order, but it always iterates in a different order than what I have defined in my code. 我正在尝试迭代我按特定顺序定义的字典,但它总是以与我在代码中定义的顺序不同的顺序迭代。 This is just a basic example of what I'm trying to do. 这只是我正在尝试做的一个基本的例子。 The dictionary I'm iterating over is much larger, has much more complexly named keys, and is not in alphabetical/numerical order. 我迭代的字典要大得多,命名密钥要复杂得多,而且不按字母/数字顺序排列。

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'

I need the order that I define the dictionary in to be preserved during iteration. 我需要在迭代期间保存我定义字典的顺序。 My order is not alphabetical, so sorting alphabetically wouldn't really help. 我的订单不是按字母顺序排列的,因此按字母顺序排序并不会有所帮助。 Is there any way to do this? 有没有办法做到这一点? I've tried `level_lookup.items(), but that doesn't maintain my order either. 我试过`level_lookup.items(),但这也不能保持我的订单。

You should use an OrderedDict . 你应该使用OrderedDict It works exactly the way you want it, however you need to define it that way. 它完全按照您的方式工作,但您需要以这种方式定义它。 Alternatively, you can have a list of keys in order, and iterate through the list and access the dictionary. 或者,您可以按顺序获得键列表,并遍历列表并访问字典。 Something along the lines of: 有点像:

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

This will be a pain to maintain, though, so I recommend you just use the OrderedDict. 但是,这将是一个难以维护,因此我建议您只使用OrderedDict。

As a last option, you could use 'constants'. 作为最后一个选项,您可以使用'常量'。 Like, 喜欢,

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

If you're fine with using the key-sorted order: 如果你使用按键排序的顺序没问题:

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

That's what I generally do if the dict is provided to me, and not something I instantiate (rather than OrderedDict . 如果dict是提供给我的话,我通常会这样做,而不是我实例化的东西(而不是OrderedDict

You could use a collections.OrderedDict . 可以使用collections.OrderedDict If that doesn't work for you, you could sort the keys before you iterate over them: 如果这对您不起作用,您可以在迭代之前对键进行排序:

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

Note however, that this particular sorting costs linear space and O(nlogn) time. 但请注意,此特定排序会花费线性空间和O(nlogn)时间。 Also, it uses the coincidental numbering system "PRIORITY_N" for sorting, which may not always be valid 此外,它使用巧合编号系统"PRIORITY_N"进行排序,这可能并不总是有效的

Try; 尝试;

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

As Jon has pointed out, keys() and iterkeys() are redundant here; 正如Jon指出的那样, keys()iterkeys()在这里是多余的;

for priority in sorted(level_lookup):

I think you would be better off not using a containg dictionary and see no compelling reason to use one in this case. 我认为你最好不要使用包含字典,并且在这种情况下没有令人信服的理由使用它。 A list would store the items in the desired order: 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

In fact, you could write the whole thing as list comprehension: 事实上,你可以把整个事情写成列表理解:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM