有没有办法';暂停';或者部分使用Python中的生成器,然后在停止的地方继续使用?
有一个相关的问题。我正在尝试在HackerRank上进行Euler项目挑战。它需要的是您能够导出字符串“abcdefghijklm”的第n个排列。有13个!排列 我尝试了一个简单的解决方案,其中我使用了num的有没有办法';暂停';或者部分使用Python中的生成器,然后在停止的地方继续使用?,python,python-3.x,iteration,generator,Python,Python 3.x,Iteration,Generator,有一个相关的问题。我正在尝试在HackerRank上进行Euler项目挑战。它需要的是您能够导出字符串“abcdefghijklm”的第n个排列。有13个!排列 我尝试了一个简单的解决方案,其中我使用了num的、zip中的stry(range(1,math.factorial(13))、itertools.permutations(“abcdefghijklm”):。这是可行的,但它超时了 真正好的做法是,在我进行操作时,将每个值存储在一个dict中,并执行如下操作: import iterto
、zip中的stry(range(1,math.factorial(13))、itertools.permutations(“abcdefghijklm”):
。这是可行的,但它超时了
真正好的做法是,在我进行操作时,将每个值存储在一个dict
中,并执行如下操作:
import itertools
import math
strt = "abcdefghijklm"
dic = {}
perms_gen = itertools.permutations(strt)
idxs_gen = range(1, math.factorial(13))
curr_idx = 0
test_list = [1, 2, 5, 10]
def get_elems(n):
for num, stry in zip(idxs_gen, perms_gen):
print(num) # debug
str_stry = "".join(stry)
dic[num] = str_stry
if num == n:
return str_stry
for x in test_list:
if curr_idx < x:
print(get_elems(x))
else:
print(dic[x])
import itertools
import math
strt = "abcdefghijklm"
dic = {}
perms_gen = itertools.permutations(strt)
idxs_gen = range(1, math.factorial(13))
main_gen = zip(idxs_gen, perms_gen)
curr_idx = 0
test_list = [1, 2, 5, 10]
def get_elems(n):
for num, stry in main_gen:
print(num)
str_stry = "".join(stry)
dic[num] = str_stry
if num == n:
return str_stry
for x in test_list:
if curr_idx < x:
print(get_elems(x))
else:
print(dic[x])
当我写这个问题时,我显然发现答案…有待继续。标题中问题的答案是“是”,您可以暂停并重新开始。如何 (对我来说)出乎意料地,
zip()
重新启动压缩的生成器,尽管它们之前已经定义好了(也许有人能告诉我为什么会发生这种情况?)。因此,我添加了main\u gen=zip(idxs\u gen,perms\u gen)
,并更改为for num,stry in zip(idxs\u gen,perms\u gen):
到对于num,stry,在main\u gen:
中。然后我得到这个输出,假设字符串是正确的,这正是我想要的:
1
abcdefghijklm
2
abcdefghijkml
3
4
5
abcdefghijmkl
6
7
8
9
10
abcdefghiklmj
更改后,代码如下所示:
import itertools
import math
strt = "abcdefghijklm"
dic = {}
perms_gen = itertools.permutations(strt)
idxs_gen = range(1, math.factorial(13))
curr_idx = 0
test_list = [1, 2, 5, 10]
def get_elems(n):
for num, stry in zip(idxs_gen, perms_gen):
print(num) # debug
str_stry = "".join(stry)
dic[num] = str_stry
if num == n:
return str_stry
for x in test_list:
if curr_idx < x:
print(get_elems(x))
else:
print(dic[x])
import itertools
import math
strt = "abcdefghijklm"
dic = {}
perms_gen = itertools.permutations(strt)
idxs_gen = range(1, math.factorial(13))
main_gen = zip(idxs_gen, perms_gen)
curr_idx = 0
test_list = [1, 2, 5, 10]
def get_elems(n):
for num, stry in main_gen:
print(num)
str_stry = "".join(stry)
dic[num] = str_stry
if num == n:
return str_stry
for x in test_list:
if curr_idx < x:
print(get_elems(x))
else:
print(dic[x])
导入itertools
输入数学
strt=“abcdefghijklm”
dic={}
置换(strt)
idxs_gen=范围(1,数学阶乘(13))
main_gen=zip(idxs_gen,perms_gen)
电流idx=0
测试列表=[1,2,5,10]
def获取元素(n):
对于num,主目录中的stry:
打印(个)
str_stry=”“.加入(stry)
dic[num]=str\u stry
如果num==n:
返回序列
对于测试列表中的x:
如果当前idx
暂停是生成器的内置功能。它是生成器的一半。但是,范围
不是生成器。它是一种惰性序列类型
如果您想要一个对象,在该对象上再次迭代将从上次停止的位置恢复,则需要一个范围对象上的迭代器:
idsx_iter = iter(range(1, math.factorial(13)))
但是,保存zip
迭代器比保存两个底层迭代器更简单。更好的方法是使用enumerate
:
indexed_permutations = enumerate(itertools.permutations(strt))
但是,你的代码中还有很多没有意义的东西,比如永远保持在0的
curr\u idx
,或者你的范围
边界,它产生13!-1个索引而不是13!个索引,实际上,你应该使用一种更有效的算法。例如,一种基于计算你需要多少个排列的算法通过将下一个元素设置为一个特定字符,并使用该字符直接计算置换的每个元素,ip将向前移动。确定您可以使用迭代器的一部分it
,只需调用next(it)
使用单个项。或者如果您需要同时使用多个项,则可以编写一个函数来使用迭代器中的n
项。在这两种情况下,您只需注意迭代器尚未结束(StopIteration
引发):
def消耗(迭代器,n):
对于范围(n)中的i:
尝试:
生成下一个(迭代器)
除停止迭代外:
返回
然后可以这样使用:
r=iter(范围(5))
>>>打印(列表(消耗(r,3)))
[0, 1, 2]
>>>打印(列表(消耗(r,3)))
[3, 4]
最后,我不明白你为什么需要这个来解决这个问题,正如我建议的那样,有一个python函数已经为你迭代了所有的置换。哪个版本的python?在Python2中,zip返回一个列表。在Python3中,zip是一个类似itertools的迭代器。izip也像itertools.imap。@DanD.python 3。我认为从代码中可以明显看出什么?
zip
不会重新启动生成器。@user2357112那么您能解释一下该代码的输出吗?