簡體   English   中英

列表理解的累計和

[英]Cumulative sum with list comprehension

我有一個整數列表:

x = [3, 5, 2, 7]

我想創建一個新列表,其中第nth元素是x0n-1的元素總和。

這將導致:

y = [0, 3, 8, 10]

如何在不運行循環的情況下使用列表理解來做到這一點?

沒有循環和列表理解如何? 遺憾的是只有 Python 3:

>>> x = [3, 5, 2, 7]
>>> from itertools import accumulate
>>> [0] + list(accumulate(x[:-1]))
[0, 3, 8, 10]

更新:這是一個 O(n) 列表理解解決方案:

>>> s = [0]
>>> [s.append(s[0]+n) or s.pop(0) for n in x]
[0, 3, 8, 10]

但我只想表明,無需太多努力即可實現。 我認為accumulate或 for 循環要好得多。

純列表推導,O(n) 時間和 O(1) 額外空間(即除了列表推導構建列表所需的空間之外)( 在線嘗試! ):

xs = [3, 5, 2, 7]
                           #  Equivalent for-loop version:
ys = [y                    #  ys = []
      for s in [0]         #  s = 0
      for x in xs          #  for x in xs:
      for y in [s]         #      y = s
      for s in [s + x]]    #      s = s + x
                           #      ys.append(y)
print(ys)

我重命名為復數xsys以便我可以命名單個值xy s是累積和,在更新s之前我記得它是y (因為你要求結果[0, 3, 8, 10]而不是[3, 8, 10, 17] )。

請注意,自 CPython 3.9 起,我for y in [s]for s in [s + x]進行了優化,因此它們實際上不會構建和迭代單元素列表,而是像y = ss = s + x一樣工作s = s + x

>>> import dis
>>> dis.dis('''ys = [y
...       for s in [0]
...       for x in xs
...       for y in [s]
...       for s in [s + x]]''')

             ...

  4          16 LOAD_FAST                1 (s)
             18 STORE_FAST               3 (y)

  5          20 LOAD_FAST                1 (s)
             22 LOAD_FAST                2 (x)
             24 BINARY_ADD
             26 STORE_FAST               1 (s)

             ...

如果您正在對列表進行計算,則使用 numpy 可能會更好:

import numpy as np
x = [3, 5, 2, 7]

print(np.cumsum([0]+x[:-1]).tolist())
[0, 3, 8, 10]

或者如果 0 無關緊要:

import numpy as np
x = np.array([3, 5, 2, 7])

print( x[:-1].cumsum())
[ 3  8 10]

或者如果你想要 0 則追加:

import numpy as np
x = np.array([3, 5, 2, 7])
out = np.array(0)
print(np.append(out, x[:-1].cumsum()))
[0  3  8 10]

無論你做什么,總會有一個循環,我會更擔心編寫高效的代碼而不是簡短的代碼。

僅使用 python2 常規 for 循環將是有效的:

x = [3, 5, 2, 7]

sm = 0
out = []
for ele in x:
    out.append(sm)
    sm += ele
print(out)
[0, 3, 8, 10]
x = [3, 5, 2, 7]

cumsumx=[sum(x[:i] for i in range(len(x))]

這提供了您所需要的:

x = [3, 5, 2, 7]
y = [sum(x[0:i]) for i,value in enumerate(x)]
[0, 3, 8, 10]

這是我剛剛發現的一個甜蜜的:

s = 0
cumsum = [(s:=s+i) for i in my_list]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM