【问题标题】:Iterating ordered dict items starting from specific key从特定键开始迭代有序 dict 项
【发布时间】:2018-08-17 02:05:40
【问题描述】:

问题的样式在 python 2.7 中。

我使用OrderedDict来存储一些项目如下:

d = OrderedDict(zip(['a', 'b', 'c', 'd'], range(4)))

d 等于 {'a': 0, 'b': 1, 'c': 2, 'd': 3}

有没有办法从特定键开始迭代字典d? 例如,我想从键 'b' 开始迭代 d 项目

非常感谢!

【问题讨论】:

  • 没有任何优雅的方法可以做到这一点。为什么不直接使用if key != 'b': continue
  • 如果你点击d,你想循环回来吗?还是您只想在点击d 后结束? (d 是关键而不是字典项:D)
  • 感谢您的评论。在实际用例中,我想消除多个项目,而不仅仅是一个。
  • 我想在迭代 d 时对列表进行切片。例如:for k in d['c':]
  • 所以保留一个你想要排除的键列表,然后if key in excluded_keys: continue

标签: python python-2.7 dictionary slice


【解决方案1】:

这行得通吗?

for x in list(a.keys())[a.index(my_key):]:
    print(a[x])

my_key 是您要开始的键

【讨论】:

    【解决方案2】:

    您可以通过使用items() 查找b 的值并在需要的位置进行切片来进行迭代。如果您有自己的方式知道要从哪里开始,请替换 d.keys().index('b')

    from collections import OrderedDict
    
    d = OrderedDict(zip(['a', 'b', 'c', 'd'], range(4)))
    
    for each in d.items()[d.keys().index('b'):]:
        print(each)
    

    使用items() 可以让您像往常一样获取键和值。

    【讨论】:

    • 我知道,你也知道我回答 Python 2 问题感觉不对,但是嗯。自操作The question is styled in python 2.7 .
    • 啊,没看到。继续;D
    • 如果我错了,请纠正我,但这不是复制整个字典吗?最好使用iteritems()
    • @jpp iteritems() 将不起作用,因为生成器没有不允许切片的 __getitem__ 调用,这正是 OP 想要的。因此,Coldspeed 的原始(已删除)评论指出这在 Py3 中不起作用,因为在 Py3 中 items() 变为 iteritems()
    【解决方案3】:

    在我看来,如果您不想索引元组列表,这是一种选择:

    from collections import OrderedDict
    from itertools import islice
    
    d = OrderedDict(zip(['a', 'b', 'c', 'd'], range(4)))
    
    for each in islice(d.iteritems(), d.keys().index('b'), None):
        print(each)
    

    【讨论】:

      【解决方案4】:

      适用于 Python 2 和 3 的解决方案,使用 itertools.dropwhile()

      from __future__ import print_function
      
      from collections import OrderedDict
      from itertools import dropwhile
      
      d = OrderedDict(zip(['a', 'b', 'c', 'd'], range(4)))
      
      for k, v in dropwhile(lambda x: x[0] != 'b', d.items()):
          print(k, v)
      

      输出:

      b 1
      c 2
      d 3
      

      Python 2,避免使用.items():: 创建键值列表

      for k, v in dropwhile(lambda x: x[0] != 'b', d.iteritems()):
          print(k, v)
      

      时间

      %timeit
      for each in d.items()[d.keys().index('b'):]:
          pass
      The slowest run took 5.18 times longer than the fastest. This could mean that an intermediate result is being cached.
      100000 loops, best of 3: 3.27 µs per loop
      
      %%timeit
      for each in islice(d.iteritems(), d.keys().index('b'), None):
          pass
      The slowest run took 5.23 times longer than the fastest. This could mean that an intermediate result is being cached.
      100000 loops, best of 3: 3.05 µs per loop
      
      %%timeit
      for k, v in dropwhile(lambda x: x[0] != 'b', d.iteritems()):
          pass
      The slowest run took 4.92 times longer than the fastest. This could mean that an intermediate result is being cached.
      100000 loops, best of 3: 2.23 µs per loop
      

      【讨论】:

      • 是的,那将是 Python 2 的改进。
      • 我发现这个解决方案最美观和优雅。与其他建议相比,您会说它也是最有效的吗?
      • 在 Python 2 中使用iteritems() 不会复制。应该有很好的性能。 Python 2 中的d.keys() 总是创建一个列表(用于其他解决方案)。这是额外的工作。
      • 添加了一些计时。此解决方案是本示例中最快的。
      猜你喜欢
      • 2020-05-15
      • 1970-01-01
      • 1970-01-01
      • 2023-01-23
      • 2017-11-13
      • 2021-08-02
      • 2014-01-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多