我正在尝试将下面的循环转换为理解。
问题是给定一个 input_list = [1, 2, 3, 4, 5]
返回一个列表,每个元素都是该索引之前的所有元素的倍数,从左到右。
因此,返回列表将是 [1, 2, 6, 24, 120]
.
我有一个正常的循环(而且还能用)。
l2r = list()
for i in range(lst_len):
if i == 0:
l2r.append(lst_num[i])
else:
l2r.append(lst_num[i] * l2r[i-1])
Python 3.8+解决方案。
lst = [1, 2, 3, 4, 5]
curr = 1
out = [(curr:=curr*v) for v in lst]
print(out)
印刷品。
[1, 2, 6, 24, 120]
其他解决方案(含 itertools.accumulate
):
from itertools import accumulate
out = [*accumulate(lst, lambda a, b: a*b)]
print(out)
好吧,你 可以 这样做(a):
import math
orig = [1, 2, 3, 4, 5]
print([math.prod(orig[:pos]) for pos in range(1, len(orig) + 1)])
这将生成你想要的东西。
[1, 2, 6, 24, 120]
基本上是通过运行一个计数器从 1
列表的大小,在每一点上计算出该位置前所有项的乘积。
pos values prod
=== ========= ====
1 1 1
2 1,2 2
3 1,2,3 6
4 1,2,3,4 24
5 1,2,3,4,5 120
(a) 只是要记住,这在运行时效率较低,因为它为每一个元素计算完整的乘积(而不是缓存最近获得的乘积)。你可以在使用 还 使你的代码更紧凑(通常是使用列表理解的原因),用类似于:
def listToListOfProds(orig):
curr = 1
newList = []
for item in orig:
curr *= item
newList.append(curr)
return newList
print(listToListOfProds([1, 2, 3, 4, 5]))
这显然不是一个列表理解,但仍然有其优势,因为它不会在你需要计算的地方弄乱你的代码。
人们似乎经常对Python中的函数解打折扣,只因为这门语言的表现力太强了,而且 允许 列表理解这样的东西,用最少的源代码做很多工作。
但是,除了函数本身之外,这个解决方案也具有单行列表理解的优点,因为它,嗯,只占一行:-)
此外,你可以自由地 变化 函数 (例如,如果你在以后的 Python 版本中找到更好的方法)。橆 必须改变代码中所有调用它的不同地方。
这 不该 如果一次迭代取决于之前的状态,那么就可以做成一个列表理解!如果目标是一个单行本,那么就可以用@AndrejKesely的解决方案来解决。
如果目标是单行本,那么有很多解决方案,@AndrejKesely的 itertools.accumulate()
是一个优秀的(+1)。 这是我的,滥用 functools.reduce()
:
from functools import reduce
lst = [1, 2, 3, 4, 5]
print(reduce(lambda x, y: x + [x[-1] * y], lst, [lst.pop(0)]))
但就列表理解而言,@AndrejKesely的基于赋值-表达式的解决方案是错误的(-1)。 这里有一个更自我包含的理解,它不会泄漏到周围的作用域中。
lst = [1, 2, 3, 4, 5]
seq = [a.append(a[-1] * b) or a.pop(0) for a in [[lst.pop(0)]] for b in [*lst, 1]]
print(seq)
但它仍然是错误的做法! 这是基于 类似问题 也因为错误的原因被上票。
对于你的列表,可能并不是有意让数字从1开始连续,但对于有意让数字从1开始连续的情况,你可以使用内置的方法。阶乘():
from math import factorial
input_list = [1, 2, 3, 4, 5]
l2r = [factorial(i) for i in input_list]
print(l2r)
产出:
[1, 2, 6, 24, 120]