【问题标题】:List comprehension with an accumulator带有累加器的列表理解
【发布时间】:2013-11-26 16:24:15
【问题描述】:

使用列表推导(或其他紧凑方法)复制这个简单函数的最佳方法是什么?

import numpy as np

sum=0
array=[]
for i in np.random.rand(100):
   sum+=i
   array.append(sum)

【问题讨论】:

  • 你在使用 numpy 吗?我知道 numpy 对这样的事情有一个很好的功能。
  • 我不会使用列表推导 - 元素应该相互独立,在这种情况下它们不是。
  • 你为什么要把它变成一个列表理解?将其保存在单独的循环中更具可读性。改成array = [0]for i in rand(100): array.append(i + array[-1]),也许吧。
  • 我的意思是 rand(100)。我一直在使用 numpy,但是没有的解决方案也很好。

标签: python list-comprehension


【解决方案1】:

在 Python 3 中,您将使用 itertools.accumulate():

from itertools import accumulate

array = list(accumulate(rand(100)))

Accumulate 产生将输入迭代的值相加的运行结果,从第一个值开始:

>>> from itertools import accumulate
>>> list(accumulate(range(10)))
[0, 1, 3, 6, 10, 15, 21, 28, 36, 45]

你可以传入不同的操作作为第二个参数;这应该是一个可调用的,它接受累积的结果和下一个值,返回新的累积结果。 operator module 非常有助于为此类工作提供标准的数学运算符;你可以用它来产生一个正在运行的乘法结果,例如:

>>> import operator
>>> list(accumulate(range(1, 10), operator.mul))
[1, 2, 6, 24, 120, 720, 5040, 40320, 362880]

该功能很容易向后移植到旧版本(Python 2、Python 3.0 或 3.1):

# Python 3.1 or before

import operator

def accumulate(iterable, func=operator.add):
    'Return running totals'
    # accumulate([1,2,3,4,5]) --> 1 3 6 10 15
    # accumulate([1,2,3,4,5], operator.mul) --> 1 2 6 24 120
    it = iter(iterable)
    total = next(it)
    yield total
    for element in it:
        total = func(total, element)
        yield total

【讨论】:

  • 这个可行,但我一直在寻找类似列表理解的紧凑用途——比如在 ipython 命令行上。
  • @Pierz:我在accumulate() 迭代器上使用了list(),为您提供了一个快速的值列表。你仍然可以在列表理解中使用它,[v for v in accumulate(rand(100))];但是,您不能使用 just 列表理解来执行此操作,因为您无权访问到目前为止生成的先前元素。
  • 的确,这是一种优雅的方法,但我不确定是否有一种巧妙的方法可以在列表理解中获得累计总和。同意这可能不是最佳实践,但在命令行上工作时使用紧凑形式很方便。
【解决方案2】:

由于您已经在使用numpy,您可以使用cumsum

>>> from numpy.random import rand
>>> x = rand(10)
>>> x
array([ 0.33006219,  0.75246128,  0.62998073,  0.87749341,  0.96969786,
        0.02256228,  0.08539008,  0.83715312,  0.86611906,  0.97415447])
>>> x.cumsum()
array([ 0.33006219,  1.08252347,  1.7125042 ,  2.58999762,  3.55969548,
        3.58225775,  3.66764783,  4.50480095,  5.37092001,  6.34507448])

【讨论】:

    【解决方案3】:

    好的,你说你不想要numpy,但无论如何这是我的解决方案。 在我看来,您只是在取累积和,因此使用 cumsum() 函数。

    import numpy as np
    result = np.cumsum(some_array)
    

    随便举个例子

    result = np.cumsum(np.random.uniform(size=100))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-29
      • 1970-01-01
      • 2013-05-10
      • 2016-02-07
      • 1970-01-01
      相关资源
      最近更新 更多