是否可以在python中将此循环转换为列表理解
我有一小段是否可以在python中将此循环转换为列表理解,python,list,while-loop,list-comprehension,Python,List,While Loop,List Comprehension,我有一小段代码,我想知道它是否可以用列表理解来编写。while循环的部分是我感兴趣的部分 >>> sum=33 >>> final_list=[] >>> LastCoin=[0, 1, 2, 1, 2, 5, 1, 2, 1, 2, 5, 1, 2, 1, 2, 5, 1, 2, 1, 2, 5, 1, 2, 1, 2, 5, 1, 2, 1, 2, 5, 1, 2, 1] >>> while su
代码
,我想知道它是否可以用列表理解
来编写。while循环的部分是我感兴趣的部分
>>> sum=33
>>> final_list=[]
>>> LastCoin=[0, 1, 2, 1, 2, 5, 1, 2, 1, 2, 5, 1, 2,
1, 2, 5, 1, 2, 1, 2, 5, 1, 2, 1, 2, 5, 1, 2, 1, 2, 5, 1, 2, 1]
>>> while sum>0:
... final_list.append(LastCoin[sum])
... sum-=LastCoin[sum]
...
>>> print final_list
[1, 2, 5, 5, 5, 5, 5, 5]
>>>
编辑
更好的解决方案
不尝试使用列表理解。改用递归。
与以前的解决方案相比更简单,执行时间除以3
LastCoin=[0, 1, 2, 1, 2, 5, 1, 2, 1, 2, 5, 1, 2,
1, 2, 5, 1, 2, 1, 2, 5, 1, 2, 1, 2, 5,
1, 2, 1, 2, 5, 1, 2, 1]
def nekst(x,L,rec=None):
if rec is None: rec = []
rec.append(L[x])
if x-L[x]>0: nekst(x-L[x],L,rec)
return rec
print nekst(33,LastCoin)
结果
[1, 2, 5, 5, 5, 5, 5, 5]
4.10056836833 Omid Raha
0.29426393578 eyquem 1
0.114381576429 eyquem 2, nekst redefined at each turn of the measurement loop
0.107410299354 eyquem 2, nekst defined outside of the measurement loop
0.0820501882362 while-loop == 76.4 % of 0.107410299354
susu == [33, 32, 30, 25, 20, 15, 10, 5]
fifi == [1, 2, 5, 5, 5, 5, 5, 5]
wanted : [1, 2, 5, 5, 5, 5, 5, 5]
比较执行时间
注意:以下测试是使用没有行的递归函数进行的
如果rec为None:rec=[]
这一行的存在稍微增加了递归函数解决方案的执行时间(+12%)
from time import clock
iterat = 10000
N = 100
LastCoin=[0, 1, 2, 1, 2, 5, 1, 2, 1, 2, 5, 1, 2,
1, 2, 5, 1, 2, 1, 2, 5, 1, 2, 1, 2, 5,
1, 2, 1, 2, 5, 1, 2, 1]
counter = 33
te = clock()
for i in xrange(iterat):
final_list = [LastCoin[reduce(lambda x, y: x - LastCoin[x],
range(counter, i, -1))]
for i in range(counter -1, 0, -1)
if reduce(lambda x, y: x - LastCoin[x],
range(counter, i, -1))]
print clock()-te,'Omid Raha'
st=33
E1 = []
for n in xrange(N):
te = clock()
for i in xrange(iterat):
susu2 = [st]
susu2.extend(x for x in xrange(st,0,-1)
if x==(susu2[-1]-LastCoin[susu2[-1]]))
fifi2 = [LastCoin[x] for x in susu2]
del fifi2
E1.append(clock()-te)
t1 = min(E1)
print t1,'eyquem 1'
E2 = []
for n in xrange(N):
te = clock()
for i in xrange(iterat):
def nekst(x,L,rec):
rec.append(L[x])
if x-L[x]>0: nekst(x-L[x],L,rec)
return rec
fifi3 = nekst(st,LastCoin,[])
del fifi3,nekst
E2.append(clock()-te)
t2 = min(E2)
print t2,'eyquem 2, nekst redefined at each turn of the measurement loop'
def nekst(x,L,rec):
rec.append(L[x])
if x-L[x]>0: nekst(x-L[x],L,rec)
return rec
E22 = []
for n in xrange(N):
te = clock()
for i in xrange(iterat):
fifi3 = nekst(st,LastCoin,[])
del fifi3
E22.append(clock()-te)
t22 = min(E22)
print t22,'eyquem 2, nekst defined outside of the measurement loop'
W = []
for n in xrange(N):
te = clock()
for i in xrange(iterat):
y = 33
final_list=[]
while y>0:
final_list.append(LastCoin[y])
y-=LastCoin[y]
del final_list,y
W.append(clock()-te)
tw = min(W)
print tw,'while-loop == %.1f %% of %s' % (100*min(W)/min(E22),min(E22))
结果
[1, 2, 5, 5, 5, 5, 5, 5]
4.10056836833 Omid Raha
0.29426393578 eyquem 1
0.114381576429 eyquem 2, nekst redefined at each turn of the measurement loop
0.107410299354 eyquem 2, nekst defined outside of the measurement loop
0.0820501882362 while-loop == 76.4 % of 0.107410299354
susu == [33, 32, 30, 25, 20, 15, 10, 5]
fifi == [1, 2, 5, 5, 5, 5, 5, 5]
wanted : [1, 2, 5, 5, 5, 5, 5, 5]
如果函数nekst()
的定义是在计时循环之外执行的,则速度会快一点
原始答案略经编辑
我做得再好不过了:
sum=33
LastCoin=[0, 1, 2, 1, 2, 5, 1, 2, 1, 2, 5, 1, 2,
1, 2, 5, 1, 2, 1, 2, 5, 1, 2, 1, 2, 5,
1, 2, 1, 2, 5, 1, 2, 1]
susu = [sum]
susu.extend(x for x in xrange(sum,0,-1)
if x==(susu[-1]-LastCoin[susu[-1]]))
fifi = [LastCoin[x] for x in susu]
print 'susu == %r\n'\
'fifi == %r\n'\
'wanted : %r' % (susu,fifi,[1, 2, 5, 5, 5, 5, 5, 5])
结果
[1, 2, 5, 5, 5, 5, 5, 5]
4.10056836833 Omid Raha
0.29426393578 eyquem 1
0.114381576429 eyquem 2, nekst redefined at each turn of the measurement loop
0.107410299354 eyquem 2, nekst defined outside of the measurement loop
0.0820501882362 while-loop == 76.4 % of 0.107410299354
susu == [33, 32, 30, 25, 20, 15, 10, 5]
fifi == [1, 2, 5, 5, 5, 5, 5, 5]
wanted : [1, 2, 5, 5, 5, 5, 5, 5]
编辑是:
如果x==(susu[-1]-LastCoin[sususu[-1]]),那么x范围内x的x值(和,0,-1)x
而不是原来的
如果x==(susu[-1]-LastCoin[sususu[-1]]),那么x范围内的x(和,-1,-1)的x的x=0
是的,有可能:
counter = 33 # your sum variable
LastCoin = [0, 1, 2, 1, 2, 5, 1, 2, 1, 2, 5, 1, 2,
1, 2, 5, 1, 2, 1, 2, 5, 1, 2, 1, 2, 5, 1, 2, 1, 2, 5, 1, 2, 1]
final_list = [LastCoin[reduce(lambda x, y: x - LastCoin[x],
range(counter, i, -1))]
for i in range(counter -1, 0, -1)
if reduce(lambda x, y: x - LastCoin[x],
range(counter, i, -1))
]
print(final_list)
# [1, 2, 5, 5, 5, 5, 5, 5]
但是,这不是导入此
的方式 您尝试使用列表理解有什么好的理由吗
我个人看到很多人试图将列表理解插入他们不属于的地方,因为,你知道,“列表理解更快——它们是用C语言编写的!”!而您的无聊循环是在“解释Python”中。这并不总是正确的
作为参考,如果我们将您简洁易读的原始解决方案与两个建议答案进行比较,您可能会发现您的假设被违反:
In [5]: %%timeit
...: sum=33
...: while sum > 0:
...: final_list.append(LastCoin[sum])
...: sum -= LastCoin[sum]
...:
100000 loops, best of 3: 1.96 µs per loop
In [6]: %%timeit
...: sum=33
...: susu = [sum]
...: susu.extend(x for x in xrange(sum,-1,-1)
...: if x==(susu[-1]-LastCoin[susu[-1]])!=0)
...: fifi = [LastCoin[x] for x in susu]
...:
100000 loops, best of 3: 10.4 µs per loop
# 5x slower
In [10]: %timeit final_list = [LastCoin[reduce(lambda x, y: x - LastCoin[x], range(counter, i, -1))] for i in range(counter -1, 0, -1) if reduce(lambda x, y: x - LastCoin[x], range(counter, i, -1))]
10000 loops, best of 3: 128 µs per loop
# More than 60x slower!!
如果您正试图对列表中的每个元素执行某些操作,那么列表理解是一个不错的选择—过滤(测试每个元素的真/假)、翻译等,其中操作对每个元素都是独立的(理论上,通常可以并行化)。它不太擅长在循环过程中处理和改变状态的循环,当你尝试时,它们通常看起来很难看。在这种特殊情况下,您在浏览列表时只查看8项,因为您要手动计算要查看的索引。在列表理解案例中,您至少需要查看所有33个
我不知道这是否是你的动机,但如果是,就把它作为一个循环。Python循环毕竟没有那么糟糕 我参加聚会可能晚了一点。在Python3.9中,我们可以使用walrus操作符(:=) 如果我们使用它,我们可以执行以下操作并将while语句缩减为一行
LastCoin=[0, 1, 2, 1, 2, 5, 1, 2, 1, 2, 5, 1, 2,
1, 2, 5, 1, 2, 1, 2, 5, 1, 2, 1, 2, 5,
1, 2, 1, 2, 5, 1, 2, 1]
s = 33
final_list = [LastCoin[s]]
while (s:=s-LastCoin[s]) > 0: final_list.append(LastCoin[s])
print (final_list)
其输出将为:
[1, 2, 5, 5, 5, 5, 5, 5]
您正在使用的迭代模式非常不规则,似乎您正在使用迭代器作为累加器和索引。你能给我们一些关于这个问题的上下文吗?可能吗?将任何
while
循环转化为列表理解的第一步是将while
循环转化为for
循环。如果没有自然的方法可以做到这一点,那么就不会有任何自然的方法将其转化为列表理解。(在最坏的情况下,总是有办法做到这一点的,你可以将循环提取到一个生成器函数中,然后final\u list=[sum for sum in my\u generator()]
…但这几乎没有用。)我想值得一提的是,sum
是一个内置函数的名称,因此,您应该为变量选择其他名称。另一种方法是(您可能不想这样做):listcomp中的表达式必须是常量值和循环迭代值。您还需要包括最后一个附加值。如果查看functools.reduce
和itertools.accumulate
,您会发现这总是可能的。我想不出任何方法来使用这个技巧使任何东西在这里甚至可以远程读取,但也许你可以。我个人不喜欢使用timeit
,我从不提醒如何使用它(我不会假装使用它是件坏事)。通过使用time.clock
进行测试,我没有发现我的解决方案的执行时间与Omid Raha的执行时间之间有太大的差异:执行Omid的解决方案的时间大约是我第一个解决方案的13倍,而不是60倍但我找到了另一个解决方案,请看,它比以前快3倍,而且更简单我赞成你比较执行时间的工作;在这里,它就像%timeit命令一样简单。我也不记得参数,但我不必:)我针对您的解决方案进行了测试-它更简单,但仍然不比原始while循环更简单。怎么可能呢?这是相同的算法,但有额外的函数调用。时间仍然很快,但在我的测试中大约慢了70%——while循环为1.66uS,递归解决方案为2.94uS(我的时间是st=33;fifi3=nekst(st,LastCoin,[])
,所以我已经从循环中重构了函数def).我刚刚浏览了IPython的网站,它让我渴望了解并使用它。看起来很有趣。谢谢你提供的信息我想知道的是:IPython是用哪种语言实现的?它是以C作为Python本身,还是以Python或其他语言为基础?好吧,谢谢您的反思。我现在想我已经把这个话题讲得精疲力尽了。下午好。我几乎不理解您的解决方案中的流程,而且它的执行时间比我的解决方案(如Corley所示)要长。无论如何,这是一个令人印象深刻的解决方案,祝贺这一“tour de force”--你可能会对我的答案编辑中的新解决方案感兴趣。如果你不尝试在一行182个字符的长行中写出所有内容,这将更加清晰。不管怎么说,看起来你在对每个值进行全范围的缩减,这使得它是二次的而不是线性的,这解释了为什么它如此缓慢。许多核心开发者喜欢说“在每个r中