将列表中的每个值设置为对先前值的某些修改?

时间:2017-02-13 20:23:27

标签: python

我们说我们有一个随机整数列表

我想获得一个新列表(或更改此列表),其中每个元素本身,或前一个元素* 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的其余部分就没用了,因为这些值也不会改变。

3 个答案:

答案 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]