[英]Using reduce to shorten a for-loop
From an array Ns
, I'd like to derive an array multipliers
as follows: 我想从数组
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]
The resulting array multipliers
is [1, 3, 9, 54]
. 结果数组
multipliers
为[1, 3, 9, 54]
。 My gut feeling is that it should be possible to make this code more succinct using reduce
or another built-in function, but I don't yet see how. 我的直觉是应该可以使用
reduce
或其他内置函数使此代码更简洁,但我还没有看到。 Any ideas? 有任何想法吗?
You could use itertools.accumulate
with a custom accumulation function (Python 3 only, if you want to use Python 2 you could install fn.py
library (or similar) or backport the function using the implementation provided in the docs) : 您可以将
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]
And then just fix the first and the last elements: 然后只需修复第一个和最后一个元素:
In [13]: l = list(accumulate([3, 3, 6, 3], func=operator.mul))
In [14]: [1] + l[:-1]
Out[14]: [1, 3, 9, 54]
You can simulate the behavior of accumulate
(see @soon's answer) in Python 2 with reduce
. 您可以使用
reduce
来模拟Python 2中accumulate
的行为(请参阅@soon的答案)。 You have to manage the list by yourself. 您必须自己管理列表。
from functools import reduce
Ns = [3, 3, 6, 3]
multipliers = reduce(lambda l, x: l + [l[-1] * x], Ns[:-1], [1])
reduce
give you just the final result of the reducing process, so if you want all the intermediate values you can use list comprehension as followed: reduce
给您减少过程的最终结果,因此,如果您需要所有中间值,则可以按照以下方式使用列表推导:
>>> [reduce(lambda x,y:x*y, Ns[:i], 1) for i in range(len(Ns))]
[1, 3, 9, 54]
but that isn't efficient since it reducing again and again for each sublist. 但这并不高效,因为它会针对每个子列表一次又一次地减少。
As my comment and other answers mention, this is easy in Python 3, using itertools.accumulate
. 正如我的评论和其他答案所提到的,在Python 3中,使用
itertools.accumulate
很容易。 However, from your previous questions it appears that you're using Python 2. 但是,从先前的问题来看,您似乎正在使用Python 2。
In Python, it's almost always better to iterate directly over a list rather than using indices. 在Python中,直接遍历列表而不是使用索引通常总是更好。 Your code could be rewritten like this.
您的代码可以这样重写。 (I've changed your list name to
ns
to comply with the PEP 8 style guide ). (为了符合PEP 8样式指南,我已将您的列表名称更改为
ns
)。
ns = [3, 3, 6, 3]
multipliers = []
last = 1
for u in ns:
multipliers.append(last)
last *= u
print multipliers
output 输出
[1, 3, 9, 54]
Note that this code does an extra multiplication at the end, the result of which doesn't get appended to multipliers
. 请注意,此代码在末尾进行了额外的乘法运算,其结果不会附加到
multipliers
。 Here's an alternative that's a little more compact. 这是一个更紧凑的选择。 Instead of using the
last
variable it looks up the last element in multipliers
, which is slightly less efficient, and while it doesn't do that extra multiplication it does need to create a new list when it slices ns
. 而不是使用
last
变量,而是在multipliers
查找最后一个元素,后者的效率稍低,尽管它没有执行额外的乘法运算,但在对ns
切片时确实需要创建一个新列表。
ns = [3, 3, 6, 3]
multipliers = [1]
for u in ns[:-1]:
multipliers.append(u * multipliers[-1])
print multipliers
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.