2012-09-02 42 views
5

你知道Python中的方便的reduce函數。例如,你可以用它來總結一個列表,像這樣(假裝沒有內置sum):Python中的reducelist:像減少但給出中間結果列表

reduce(lambda x,y: x+y, [1,2,3,4], 0) 

返回(((0 + 1)+ 2)+3)+ 4 = 10.

現在如果我想要一箇中間和的列表呢?在這種情況下,[1,3,6,10]

這是一個醜陋的解決方案。有更多pythonic嗎?

def reducelist(f, l, x): 
    out = [x] 
    prev = x 
    for i in l: 
    prev = f(prev, i) 
    out.append(prev) 
    return out 
+0

僅供參考,至少在Haskell中,這被稱爲* scan *。在函數式編程領域,Reduce也被稱爲(特定種類)* fold *。 – delnan

+0

感謝delnan,是的,我知道這是來自Mathematica的FoldList。 Mathematica具有許多這些函數式編程函數的累積版本,通過追加「List」來表示。我從下面的答案中看到,在Python 3中,我稱之爲reducelist現在可用作accumulate()。 – dreeves

回答

8

我最喜歡的,如果你足夠新:

Python 3.2.1 (default, Jul 12 2011, 22:22:01) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import itertools 
>>> itertools.accumulate([1,2,3,4]) 
<itertools.accumulate object at 0x1006baad0> 
>>> list(itertools.accumulate([1,2,3,4])) 
[1, 3, 6, 10] 

accumulate也接受一個函數參數[甚至更近,though-- 3.3]:

>>> list(itertools.accumulate([1,2,3,4], lambda x,y: x+y)) 
[1, 3, 6, 10] 
>>> list(itertools.accumulate([1,2,3,4], lambda x,y: x+y+1)) 
[1, 4, 8, 13] 
+0

啊,真好!雖然對我來說,這兩者都是最近的(我在Python 2中)並且太具體(這只是爲了總結,而不是我正在尋找的一般reducer)。編輯:啊,它*是*一般足夠,與該可選參數;謝謝! – dreeves

8

如果您使你的解決方案發生器更短,並且更好地服從函數式編程風格。我會爲X加0的默認值也:

def reducelist(f, lst, x=0): 
    prev = x 
    for i in lst: 
    prev = f(prev, i) 
    yield prev 

這絕對更Python的

+0

謝謝!如果您需要返回實際列表,該怎麼辦?我們可以在函數內進行轉換嗎?這還會比通過反覆附加構建列表更好嗎? – dreeves

+0

我將它留給該函數的用戶來將生成器轉換爲具有'list'功能的列表。如果你想要一個直接返回列表的函數,你可以創建一個輔助函數'reducelist_helper(f,lst,x = 0):return list(reducelist(f,lst,x))' – halex