[英]How to reset and shuffle a "next" iterator?
我有一个 function 生成从 -180 到 180 的数字:
all_angles = list(range(-180,180))
random.shuffle(all_angles)
next_angle = iter(all_angles)
问题是它在 360 之后停止生成(这是有道理的,因为它是从 -180 到 180):
n_list = []
for i in range(1000):
n_list.append(next(next_angle))
print(len(n_list))
>>> 360 # currently it only prints 360
一旦超过所有 360 值,我如何重置它并随机播放它? 所以上面for loop
会生成 360 个打乱的数字,在遍历所有 360 个值后重置(每个值只出现一次),然后生成另一组 360 个值,依此类推。
生成器无休止地洗牌和让步:
def endless_shuffling(iterable):
values = list(iterable)
while True:
random.shuffle(values)
yield from values
而不是你的iter(all_angles)
,使用endless_shuffling(all_angles)
(并删除你自己的其他洗牌)。
然后获取列表的一种方法:
random_angles = endless_shuffling(range(-180, 180))
n_list = list(islice(random_angles, 1000))
如果你给它一个空的可迭代对象并要求它提供一个值,它会“挂起”,所以要么不要这样做,要么防范这种情况(例如,使用额外的if values:
或使用while values:
)。
我还尝试了一种比通过生成器发送每个值更快的迭代方法,但是改组占主导地位,因此没有太大的区别:
with shuffling:
448.3 ms endless_shuffling1
426.7 ms endless_shuffling2
without shuffling:
26.4 ms endless_shuffling1
5.1 ms endless_shuffling2
完整代码( 在线试用! ):
from random import shuffle
from itertools import chain, islice
from timeit import default_timer as time
def endless_shuffling1(iterable):
values = list(iterable)
while True:
shuffle(values)
yield from values
def endless_shuffling2(iterable):
values = list(iterable)
return chain.from_iterable(iter(
lambda: shuffle(values) or values,
[]
))
funcs = endless_shuffling1, endless_shuffling2
for f in funcs:
print(*islice(f('abc'), 21))
for i in range(6):
for f in funcs:
t0 = time()
next(islice(f(range(-180,180)), 999999, 1000000))
print('%5.1f ms ' % ((time() - t0) * 1e3), f.__name__)
print()
if i == 2:
print('without shuffling:\n')
def shuffle(x):
pass
尝试这个。 如果在调用next
时收到错误,它会重新洗牌:
import random
all_angles = list(range(-180,180))
random.shuffle(all_angles)
next_angle = iter(all_angles)
n_list = []
for i in range(1000):
try:
n_list.append(next(next_angle))
except StopIteration:
random.shuffle(all_angles)
next_angle = iter(all_angles)
n_list.append(next(next_angle))
print(len(n_list)) # 1000
如果你想在到达终点后重新洗牌,我不知道有什么标准工具可以做到这一点。 但是您可以编写自己的可迭代对象。
import random
class Shuffler:
def __init__(self, sequence):
self.collection = list(sequence)
self.reshuffle()
def reshuffle(self):
random.shuffle(self.collection)
self.c_iter = iter(self.collection)
def __iter__(self):
return self
def __next__(self):
if not self.collection:
raise StopIteration
while True:
try:
return next(self.c_iter)
except StopIteration:
self.reshuffle()
all_angles = list(range(-180,180))
shuffler = Shuffler(all_angles)
next_angle = iter(shuffler)
n_list = []
for i in range(1000):
n_list.append(next(next_angle))
print(len(n_list)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.