【问题标题】:Iterating all Python list values starting at a specific index从特定索引开始迭代所有 Python 列表值
【发布时间】:2017-11-13 02:21:12
【问题描述】:

有没有办法循环遍历 Python 列表中的所有值,但从特定索引开始?

例如:

li = ['a', 'b', 'c', 'd']

从索引 1 开始循环并打印出结果。我的预期输出是:

['b', 'c', 'd', 'a']

我知道使用两个“for 循环”可以完成这项工作,但有没有更好的方法来做到这一点?

【问题讨论】:

  • 列表有多大?

标签: python list python-3.x indexing iteration


【解决方案1】:

好吧,你可以只使用内置的collections.deque 类,它支持"rotating"

>>> from collections import deque

>>> li = deque(['a', 'b', 'c', 'd'])
>>> li.rotate(-1)
>>> li
deque(['b', 'c', 'd', 'a'])

以防万一您真的想要一个列表作为结果,您可以随时再次将其转换回来:

>>> list(li)
['b', 'c', 'd', 'a']

【讨论】:

    【解决方案2】:

    你可以通过切片来做到这一点:

    l2 = [*li[1:], *li[:1]]
    for i in l2:
        print(i)
    

    这适用于 Python >= 3.5。对于之前的版本,您可以使用 li[1:] + li[:1]chain(li[1:],li[:1]) 和来自 itertoolschain

    或者,您可以使用 itertools 模块中的另外两个助手:

    # call list on it if you need a list object
    it = islice(cycle(li), 1, len(li)+1)    
    for i in it:
        print(i)
    

    这不会创建额外的列表。

    【讨论】:

    • for i in li[1:] + li[:1]: print(i) 适用于任何版本的 python 并且是 IMO 最简单的解决方案。
    【解决方案3】:

    您可以定义自己的生成器函数looper,然后循环通过它返回的生成器。生成器函数将列表作为第一个参数,并将所需的起始索引作为第二个输入。模运算符 (%) 可以将索引保持在列表的范围内。

    def looper(my_list, starting_ix):
        len_ml = len(my_list)
        for i in range(starting_ix, len_ml + starting_ix):
            yield my_list[i % len_ml]
    
    li = ['a', 'b', 'c', 'd']
    
    for item in looper(li, 1):
        print item
    

    【讨论】:

      【解决方案4】:

      这个呢?

      在列表后追加列表,并将start_index 迭代到start_index+len(list)

      ary = [1,2,3,4,5]
      start_idx = 3
      for num in (ary+ary)[start_idx:start_idx+len(ary)]:
          print(num)
      

      【讨论】:

      • 您忘记了]start_idx+len(ary) 之后的结束。此外,“列表后追加列表”也称为“连接”(只是为了澄清 - 我想每个人都知道你的意思)。 :)
      • 我修正了我的答案错字。我英语不好,希望你能理解。
      • 你插错地方了:应该是[start_idx:start_idx+len(ary)](注意最后两个字符的顺序不同)。 :)
      • 我很抱歉......我很头晕因为最终测试。 ㅠㅠ
      • 没问题!感谢更新。通常我会自己进行编辑,但是仅仅添加一个字符就编辑您的帖子感觉不对。 :)
      【解决方案5】:

      虽然推荐使用内置函数,但您仍然可以像这样自己做。

      要回答您关于迭代(使用简单的索引操作)的问题:

      li = ['a', 'b', 'c', 'd']
      i_offset = 1
      for i in range(len(li)):
          print (li[(i+i_offset) % len(li)])
      

      回答您关于打印列表的问题(以更 Python 的方式):

      li = ['a', 'b', 'c', 'd']
      i_offset = 1
      print ([li[(i+i_offset) % len(li)] for i,x in enumerate(li)])
      

      无需转成队列再转回列表即可实现。

      【讨论】:

      • 你说得对,deque 不是解决问题所必需的 - 但它是内置的(因此每个人都可以访问它)并且它天生支持旋转。因此,即使没有必要使用它也会使代码更容易并且(可能)更快。请注意,将其转换回来是完全可选的(如果这不明显,我可以在我的回答中更清楚地说明),deque 本身就像一个列表,当涉及到迭代时。我也很高兴您编辑了答案,现在它实际上解决了问题。 :)
      • 另请注意,该问题已标记为 python-3.x,因此您可能应该将括号 (()) 添加到 prints。
      • 感谢@MSeifert 的输入,我编辑了我的答案。您的回答确实很有趣,因此它显示了一个不错的 Python 功能,并且这是使用内置函数更容易的好方法。我认为它不会更快,因为 Python 文档提到 deque 将所有元素附加到新对象中。您对我的第一个答案是正确的,我不应该在深夜这样做:)
      • 我知道deque 更快。在评论您的答案之前,我已经计时了。 :)
      猜你喜欢
      • 2019-05-25
      • 2011-09-03
      • 2014-01-15
      • 1970-01-01
      • 1970-01-01
      • 2014-03-04
      • 2018-08-17
      • 2018-12-04
      • 2021-02-23
      相关资源
      最近更新 更多