我们说我们有一个随机整数列表
我想获得一个新列表(或更改此列表),其中每个元素本身,或前一个元素* 2(以较大者为准)
一种方法是:
a = [-1, 0, 5, -2, 1]
for i in range(1:len(a)):
a[i] = max(a[i], a[i-1] * 2)
#result should be [-1, 0, 5, 10, 20]
但是,有一些创造性的方法可以在一行中完成吗?是否有一些聪明的使用像lambda,map或iterator用来获得相同的结果?
我尝试使用zip来创建每个值和前一个值的对,但是一旦我们更改了一个元素,zip的其余部分就没用了,因为这些值也不会改变。
答案 0 :(得分:2)
在Python3中:
a = [-1, 0, 5, -2, 1]
list(itertools.accumulate(a, lambda acc, x: max(2 * acc, x))
>>> [-1, 0, 5, 10, 20]
但是,Python 2没有这么简单的运气:
def agg(acc, x):
return acc + [max(2 * acc[-1], x)]
reduce(agg, a[1:], a[0:1])
>>> [-1, 0, 5, 10, 20]
你可以通过哨兵来解决这个问题:
def agg(acc, x):
return acc + [max(2 * acc[-1], x)] if acc else [x]
reduce(agg, a, None)
>>> [-1, 0, 5, 10, 20]
关于这种“被滥用”reduce()
的(有时)好事是acc
到目前为止已经有完整的转换历史记录。
答案 1 :(得分:1)
您可以使用在Python 3.2中添加到accumulate
模块的itertools
函数或编写自己的函数:
try:
from itertools import accumulate # added in Py 3.2
except ImportError:
def accumulate(iterable):
"""Return running totals (simplified version)."""
total = next(iterable)
yield total
for value in iterable:
total += value
yield total
答案 2 :(得分:0)
如果您打算使用自己的生成器功能,可以执行以下操作:
def twice_if_bigger(iterable):
preval = next(iterable)
yield preval
for value in iterable:
preval=max(2*preval,value)
yield preval
a = [-1, 0, 5, -2, 1]
print([i for i in twice_if_bigger(a.__iter__())])
>> [-1, 0, 5, 10, 20]