【问题标题】:How to iterate over a Python dictionary in defined order?如何以定义的顺序迭代 Python 字典?
【发布时间】:2013-07-15 00:34:38
【问题描述】:

我正在尝试迭代我以特定顺序定义的字典,但它总是以与我在代码中定义的顺序不同的顺序进行迭代。这只是我正在尝试做的一个基本示例。我正在迭代的字典要大得多,具有更复杂的命名键,并且不按字母/数字顺序。

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(),但这也不能维持我的顺序。

【问题讨论】:

  • 如果您想按特定顺序使用常规字典...don't。请改用OrderedDict
  • 字典没有订单。也就是说,当您迭代时,项目必须以某种顺序出现,但这对于 Python 来说是最简单的,并且可能类似于或可能不类似于放入项目的顺序,并且可能会在您添加或删除项目时发生变化。如果您希望您的商品按顺序排列,请使用维护商品顺序的容器,例如collections.OrderedDict

标签: python loops dictionary


【解决方案1】:

可以使用collections.OrderedDict。如果这对您不起作用,您可以在迭代之前对键进行排序:

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

但是请注意,这种特殊的排序需要线性空间和 O(nlogn) 时间。此外,它使用巧合编号系统"PRIORITY_N" 进行排序,这可能并不总是有效

【讨论】:

    【解决方案2】:

    试试;

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

    正如 Jon 所指出的,keys()iterkeys() 在这里是多余的;

    for priority in sorted(level_lookup):
    

    【讨论】:

    • iterkeys() 等......在这里是多余的......只需使用sorted(level_lookup) - 它适用于 Python 2 和 3
    • 可爱的答案。不知道为什么这不是首选的“正确”答案。
    【解决方案3】:

    如果您可以使用按键排序顺序:

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

    如果dict 提供给我,我通常会这样做,而不是我实例化的东西(而不是OrderedDict

    【讨论】:

      【解决方案4】:

      您应该使用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, ...}
      

      【讨论】:

        【解决方案5】:

        我认为您最好使用包含字典,并且认为在这种情况下没有令人信服的理由使用包含字典。 Alist将按所需顺序存储项目:

        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
        

        【讨论】:

        • 这可行,但还有其他代码部分依赖于根据键进行字典查找。我可以遍历一个列表,但保持这种方式比每次在已知键时查找内容时都遍历一个非常大的列表更简洁。
        猜你喜欢
        • 1970-01-01
        • 2022-11-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-06-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多