从数组Ns
,我想按如下方式派生一个数组multipliers
:
Ns = [3, 3, 6, 3]
multipliers = [0]*len(Ns)
multipliers[0] = 1
for n in range(1,len(Ns)):
multipliers[n] = multipliers[n-1] * Ns[n-1]
生成的数组multipliers
为[1, 3, 9, 54]
。我的直觉是,应该可以使用reduce
或其他内置函数使这段代码更简洁,但我还没有看到如何。有什么想法吗?
答案 0 :(得分:5)
您可以将itertools.accumulate
与自定义累积功能一起使用(仅限Python 3,如果您想使用Python 2,则可以安装fn.py
库(或类似)或使用文档):
In [10]: from itertools import accumulate
In [11]: import operator
In [12]: list(accumulate([3, 3, 6, 3], func=operator.mul))
Out[12]: [3, 9, 54, 162]
然后修复第一个和最后一个元素:
In [13]: l = list(accumulate([3, 3, 6, 3], func=operator.mul))
In [14]: [1] + l[:-1]
Out[14]: [1, 3, 9, 54]
答案 1 :(得分:3)
您可以使用accumulate
在Python 2中模拟reduce
(请参阅@ soon的答案)的行为。您必须自己管理列表。
from functools import reduce
Ns = [3, 3, 6, 3]
multipliers = reduce(lambda l, x: l + [l[-1] * x], Ns[:-1], [1])
答案 2 :(得分:2)
reduce
只提供缩小过程的最终结果,因此如果您想要所有中间值,可以使用列表推导,如下所示:
>>> [reduce(lambda x,y:x*y, Ns[:i], 1) for i in range(len(Ns))]
[1, 3, 9, 54]
但这并不高效,因为它会逐渐减少每个子列表。
答案 3 :(得分:2)
正如我的评论和其他答案所提到的,在Python 3中使用itertools.accumulate
很容易。但是,从您之前的问题看来,您使用的是Python 2。
在Python中,直接迭代列表而不是使用索引几乎总是更好。您的代码可以像这样重写。 (我已将您的列表名称更改为ns
以符合PEP 8 style guide)。
ns = [3, 3, 6, 3]
multipliers = []
last = 1
for u in ns:
multipliers.append(last)
last *= u
print multipliers
<强>输出强>
[1, 3, 9, 54]
请注意,此代码在末尾执行额外的乘法运算,其结果不会附加到multipliers
。这是一个更紧凑的替代品。它不是使用last
变量,而是查找multipliers
中的最后一个元素,效率略低,虽然它没有进行额外的乘法,但它需要在切片时创建一个新的列表ns
。
ns = [3, 3, 6, 3]
multipliers = [1]
for u in ns[:-1]:
multipliers.append(u * multipliers[-1])
print multipliers