【问题标题】:Cycle through list starting at a certain element从某个元素开始循环遍历列表
【发布时间】:2012-01-20 11:30:06
【问题描述】:

假设我有一个清单:

l = [1, 2, 3, 4]

我想循环浏览它。通常,它会做这样的事情,

1, 2, 3, 4, 1, 2, 3, 4, 1, 2...

我希望能够从循环中的某个点开始,不一定是索引,但可能匹配一个元素。假设我想从列表==4 中的任何元素开始,那么输出将是,

4, 1, 2, 3, 4, 1, 2, 3, 4, 1...

我怎样才能做到这一点?

【问题讨论】:

    标签: python list cycle


    【解决方案1】:

    查看itertools 模块。它提供了所有必要的功能。

    from itertools import cycle, islice, dropwhile
    
    L = [1, 2, 3, 4]
    
    cycled = cycle(L)  # cycle thorugh the list 'L'
    skipped = dropwhile(lambda x: x != 4, cycled)  # drop the values until x==4
    sliced = islice(skipped, None, 10)  # take the first 10 values
    
    result = list(sliced)  # create a list from iterator
    print(result)
    

    输出:

    [4, 1, 2, 3, 4, 1, 2, 3, 4, 1]
    

    【讨论】:

    • dropwhile 在这里似乎没有必要。你可以改用list(islice(cycled, L.index(4), L.index(4) + 9))
    【解决方案2】:

    使用算术mod 运算符。假设您从位置k 开始,那么k 应该像这样更新:

    k = (k + 1) % len(l)
    

    如果你想从某个元素开始,而不是索引,你总是可以像 k = l.index(x) 一样查找它,其中 x 是所需的项目。

    【讨论】:

      【解决方案3】:

      当您只需几行代码就可以自己完成工作时,我不太喜欢导入模块。这是我没有导入的解决方案:

      def cycle(my_list, start_at=None):
          start_at = 0 if start_at is None else my_list.index(start_at)
          while True:
              yield my_list[start_at]
              start_at = (start_at + 1) % len(my_list)
      

      这将返回一个(无限)迭代器循环您的列表。要获取循环中的下一个元素,您必须使用 next 语句:

      >>> it1 = cycle([101,102,103,104])
      >>> next(it1), next(it1), next(it1), next(it1), next(it1)
      (101, 102, 103, 104, 101) # and so on ...
      >>> it1 = cycle([101,102,103,104], start_at=103)
      >>> next(it1), next(it1), next(it1), next(it1), next(it1)
      (103, 104, 101, 102, 103) # and so on ...
      

      【讨论】:

      • itertools 写成C。所以,除了口才,还是挺快的。
      • 我最喜欢这个答案。
      【解决方案4】:
      import itertools as it
      l = [1, 2, 3, 4]
      list(it.islice(it.dropwhile(lambda x: x != 4, it.cycle(l)),  10))
      # returns: [4, 1, 2, 3, 4, 1, 2, 3, 4, 1]
      

      所以你想要的迭代器是:

      it.dropwhile(lambda x: x != 4, it.cycle(l))
      

      【讨论】:

      • @gnibbler 需要将4 放在括号(4).__cmp__ 中。否则它不起作用(至少在 Python 2.7.2 中)。加上括号,它看起来并不那么漂亮。
      • @gnibbler 从 Python 3 开始,需要使用 __eq__ 而不是 __cmp__(在版本 3 中没有 __cmp__)。
      • @ovgolovin @gnibbler 写的内容没有括号。你错过了4 和. 之间的空格吗?
      • 4 和 . ?那里到底发生了什么?
      • @wim,如果你写4.__cmp__,Python 会将其解析为浮点数4.,后跟标识符__cmp__,这是语法错误。另一方面,4 .__cmp__ 是整数4,后跟一个句点,表示属性引用和属性__cmp__。
      【解决方案5】:

      嗯,http://docs.python.org/library/itertools.html#itertools.cycle 没有这样的开始元素。

      也许你只是开始循环并丢弃你不喜欢的第一个元素。

      【讨论】:

        【解决方案6】:

        另一个奇怪的选择是循环遍历列表可以向后完成。例如:

        # Run this once
        myList = ['foo', 'bar', 'baz', 'boom']
        myItem = 'baz'
        
        # Run this repeatedly to cycle through the list
        if myItem in myList:
            myItem = myList[myList.index(myItem)-1]
            print myItem
        

        【讨论】:

          【解决方案7】:

          可以这样使用:

          def my_cycle(data, start=None):
            k = 0 if not start else start
            while True:
              yield data[k]
              k = (k + 1) % len(data)
          

          然后运行:

          for val in my_cycle([0,1,2,3], 2):
            print(val)
          

          与之前的答案之一基本相同。我的错。

          【讨论】:

            猜你喜欢
            • 2018-07-11
            • 2017-10-24
            • 2018-09-05
            • 2017-02-08
            • 2014-03-03
            • 2014-11-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多