def f(nums):
sum = 0
for i in nums:
sum += i
yield sum
根据args nums(类型列表),我试图使用列表推导来创建一个新列表,该列表的每个索引值都是以前的累加值。
最终结果看起来像[i for i in f(nums)]
是否可以将函数转换为lambda表达式?或其他任何使它成为一行的东西?
答案 0 :(得分:4)
这是一种实现方法:
nums=[1,2,3,4]
[sum(nums[:idx+1]) for idx, i in enumerate(nums)]
输出:
[1, 3, 6, 10]
另一种方法是使用@Blckknght建议的itertools.accumulate。
from itertools import accumulate
list(accumulate(nums))
输出:
[1, 3, 6, 10]
答案 1 :(得分:1)
我将建议以下内容代替
:nums=[1,2,3,4]
gen=(sum(li[0:i]) for i,_ in enumerate(li,1))
这是一个生成器,因此尚未对不需要的元素执行O(n^2)
操作。
然后使用next
来获取元素:
>>> next(gen)
1
>>> next(gen)
3
>>> next(gen)
6
>>> next(gen)
10
如果您一次想要它们,只需在生成器上使用list
:
>>> gen=(reduce(add, li[0:i]) for i,_ in enumerate(li,1))
>>> list(gen)
[1, 3, 6, 10]]
此功能在非平凡列表上的性能很差,因为它的复杂度为O(n^2)
。只是出于好奇。请参见下面的时间。
(感谢AChampion)另一个减少:
>>> reduce(lambda x, y: x+[y+next(iter(x[-1:]), 0)], nums, [])
[1, 3, 6, 10]
但是正确的答案是itertools.accumulate
或您的原始功能。任何一行解决方案都将具有更大的计算复杂性。
以下是一组时序,表明除itertools.accumulate
之外,单行替换还具有O(n^2)
类型的复杂性(即,多10倍的项目,大约100倍的时间)。这是因为对于列表中的每个元素,由于lambda或reduce或comprehensions没有任何形式的累加器,因此必须再次循环到该点为止的整个列表。您的原始函数和itertools.accumulate
的类型复杂度均为O(n)
(即,项目增加10倍,线性时间增加10倍)。
Here是O复杂度的图形和备忘单。
时间和结果如下:
from itertools import accumulate
from functools import reduce
def f1(nums):
sum_ = 0
for i in nums:
sum_ += i
yield sum_
def f2(nums):
return (sum(nums[0:i]) for i,_ in enumerate(nums,1))
def f3(nums):
return accumulate(nums)
def f4(nums):
return reduce(lambda x, y: x+[y+next(iter(x[-1:]), 0)], nums, [])
if __name__=='__main__':
import timeit
for case, x in (('small',100),('med',1000),('large',10000),('huge',100000)):
data=list(range(x))
print("Case {}, {:,} x, All equal: {}".format(case,x,(list(f1(data))==list(f2(data))==list(f3(data))==list(f4(data)))))
for f in (f1,f2,f3,f4):
print(" {:^10s}{:.4f} secs".format(f.__name__, timeit.timeit("list(f(data))", setup="from __main__ import f, data", number=10)))
结果:
Case small, 100 x, All equal: True
f1 0.0001 secs
f2 0.0007 secs
f3 0.0000 secs
f4 0.0006 secs
Case med, 1,000 x, All equal: True
f1 0.0007 secs
f2 0.0424 secs
f3 0.0003 secs
f4 0.0139 secs
Case large, 10,000 x, All equal: True
f1 0.0083 secs
f2 3.9526 secs
f3 0.0036 secs
f4 1.2756 secs
Case huge, 100,000 x, All equal: True
f1 0.0977 secs
f2 427.4129 secs
f3 0.0532 secs
f4 159.2506 secs
答案 2 :(得分:0)
如果列表是连续的。
一种简单但不高效的方法:
[sum(range(1, i+1)) for i in range(1, 5))]
输出:
[1, 3, 6, 10]