我有一张单子
nums=[1,2,4,6]
我想用上限5来累加这个列表,即如果累加值超过5的倍数,它应该打印5的倍数的值,然后再打印该值
预期产量:
1
3
5
7
10
13
编写的代码如下:
nums=[1,2,4,6]
from itertools import accumulate
a= accumulate(nums)
for i in a:
print(i)
正在打印的输出
1
3
7
13
我怎样才能得到想要的输出
最佳答案
下面是使用生成器表达式的pythonic方法:
In [12]: from itertools import accumulate, chain
In [13]: list(chain.from_iterable((i,) if i < 5
else (next(j for j in range(i, 0, -1) if j%5 == 0), i)
for i in accumulate(nums)))
Out[13]: [1, 3, 5, 7, 10, 13]
其逻辑是循环累加的结果,然后对于大于5的数字,在它之前找到第一个数字(使用反向范围和
next
函数),它是5的倍数。然后使用itertools.chain()
连接结果。从算法的角度来看,不是在列表中执行多个循环,而是通过一个累加和另一个循环来寻找期望的数字,您可以在一个遍历中这样做:
In [18]: def myaccumulate(lst):
...: total = 0
...: for num in lst:
...: total += num
...: for i in range(total, num, -1):
...: if i%5 == 0:
...: yield i
...: break
...: yield total
...:
演示:
In [19]: list(myaccumulate(nums))
Out[19]: [1, 3, 5, 7, 10, 13]
这种方法实际上比基于生成器的方法更快:
In [20]: %timeit list(myaccumulate(nums))
2.65 µs ± 47.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [21]: %timeit list(chain.from_iterable((i,) if i < 5 else (next(j for j in range(i, 0, -1) if j%5 == 0), i) for i in accumulate(nums)))
4.12 µs ± 21.3 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)