如何从Python中的特定点开始Itertools循环?

问题描述 投票:0回答:5

我使用下面的代码为英文字母创建了一个

itertools
循环,

lowercase_letters_cycle = itertools.cycle(string.ascii_lowercase)

如果我在此迭代器对象上运行

for
循环,第一次迭代会给我“a”作为输出,因为循环从“a”开始。我怎样才能使循环从我选择的任何字母开始?

一种有效的方法是,

def start_cycle(letter):
  lowercase_letters_cycle = itertools.cycle(lowercase_letters)
  letter_index = lowercase_letters.index(letter)
  index = 0

  while True:
    if index == letter_index:
      break

    letter = next(lowercase_letters_cycle)
    index += 1

  return lowercase_letters_cycle

但是有没有更短的方法?

python loops python-itertools
5个回答
2
投票

itertools
文档提供了一个食谱,用于使用迭代器中的多个项目。

from itertools import islice
import collections


def consume(iterator, n=None):
    "Advance the iterator n-steps ahead. If n is None, consume entirely."
    # Use functions that consume iterators at C speed.
    if n is None:
        # feed the entire iterator into a zero-length deque
        collections.deque(iterator, maxlen=0)
    else:
        # advance to the empty slice starting at position n
        next(islice(iterator, n, n), None)

因此,您创建了循环,然后在继续之前消耗了一些它。

lowercase_letters_cycle = itertools.cycle(string.ascii_lowercase)

consume(lowercase_letters_cycle, ord('n') - ord('a'))

assert next(lowercase_letters_cycle) == 'n')

同样的

consume
也可以从第三方
more-itertools
获得。


1
投票

您可以组合

islice
模块中的
cycle
itertools
,如下所示:

import string 
import itertools

my_it = itertools.islice(itertools.cycle(string.ascii_lowercase), 3, None)

它将产生

d
(前 3 个字符之后的字符),然后是
e
,....,然后是
z
,然后是
a
,然后是
b
,依此类推。您可以将第二个参数中的数字更改为
islice
以从不同的字母开始。


1
投票

您可以对输入列表进行切片以从您选择的索引开始。

offset = 10
lowercase_letters = list(string.ascii_lowercase)

#                 offset_index to end       + start to offset_index-1
offset_letters = lowercase_letters[offset:] + lowercase_letters[:offset]
offset_letters_cycle = itertools.cycle(offset_letters)

那么,

for i in range(10):
    print(next(offset_letters_cycle), end=" ")

打印:

k l m n o p q r s t 

1
投票

import string
from itertools import cycle, dropwhile

def start_cycle(letter):
    return dropwhile(lambda x: x!= letter, cycle(string.ascii_lowercase))

itertools.dropwhile
会将可迭代的结果提供给其哨兵函数 - 在本例中为
lambda x: x != letter
,并将“吞噬”结果,直到函数第一次返回
False
。那时 该函数不再被调用,并且可迭代继续进行,产生任何 进一步的价值。

另外,请注意,无需将

ascii_lowercase
转换为列表, 因为字符串已经是可迭代的了。

请记住,如果传递的字符不是 ascii_lowercase,这将陷入 100% CPU 的无限循环。最好用支票来守护:


def start_cycle(letter):
    if letter not in string.ascii_lowercase:
         raise ValueError()
    return dropwhile(lambda x: x!= letter, cycle(string.ascii_lowercase))


0
投票

如果您只想从某个特定点开始浏览列表,您可以这样做:

my_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
start_index = 4

for i in my_list[start_index:]+my_list[:start_index]:
    print(i)
© www.soinside.com 2019 - 2024. All rights reserved.