如何从 Python 中的特定点开始 Itertools 循环?
How to start Itertools cycle from a particular point in Python?
我使用下面的代码为英文字母表创建了一个 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
但是有没有更短的方法呢?
您可以只对输入列表进行切片以从您选择的索引开始。
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
itertools
文档提供了一个 recipe 用于使用迭代器中的多个项目。
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
也可以从 third-party more-itertools
package 获得。
您可以组合 itertools
模块中的 islice
和 cycle
,如下所示:
import string
import itertools
my_it = itertools.islice(itertools.cycle(string.ascii_lowercase), 3, None)
它将产生d
(前3个字符之后的字符),然后是e
,....,然后是z
,然后是a
,然后 b
,依此类推。您可以将第二个参数中的数字更改为 islice
以从不同的字母开始。
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
,并将“吞噬”结果直到函数 returns False
for第一次。在那时候
该函数不再被调用,可迭代继续进行,产生任何
进一步的价值。
此外,请注意无需将 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))
我使用下面的代码为英文字母表创建了一个 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
但是有没有更短的方法呢?
您可以只对输入列表进行切片以从您选择的索引开始。
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
itertools
文档提供了一个 recipe 用于使用迭代器中的多个项目。
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
也可以从 third-party more-itertools
package 获得。
您可以组合 itertools
模块中的 islice
和 cycle
,如下所示:
import string
import itertools
my_it = itertools.islice(itertools.cycle(string.ascii_lowercase), 3, None)
它将产生d
(前3个字符之后的字符),然后是e
,....,然后是z
,然后是a
,然后 b
,依此类推。您可以将第二个参数中的数字更改为 islice
以从不同的字母开始。
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
,并将“吞噬”结果直到函数 returns False
for第一次。在那时候
该函数不再被调用,可迭代继续进行,产生任何
进一步的价值。
此外,请注意无需将 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))