2011-01-19 121 views
11

編寫一個返回列表運行總和的函數。例如運行[1,2,3,5]是[1,3,6,11]。我寫了這個函數,在這個函數下面可以返回列表中所有值的最後總和。那麼我怎樣才能將它們逐一分開呢?在Haskell中計算列表累計和

sumlist' xx=aux xx 0 
    where aux [] a=a 
      aux (x:xs) a=aux xs (a+x) 

回答

9

您可以調整功能,通過簡單地在前面加上a+x對每個步驟的結果,並使用空列表作爲基礎的情況下,產生一個列表:

sumlist' xx = aux xx 0 
    where aux [] a = [] 
      aux (x:xs) a = (a+x) : aux xs (a+x) 

然而,它是更地道的Haskell來表達這種作爲摺疊或掃描的東西。

25

我想你想的scanl1和組合(+),所以像

scanl1 (+) *your list here* 

scanl1將應用給定函數跨名單,並報告每一箇中間值到返回的列表。

一樣,寫出來的僞代碼,

scanl1 (+) [1,2,3] 

將輸出就像一個列表:

[1, 1 + 2, 1 + 2 + 3] 

,或者換句話說,

[1, 3, 6] 

Learn You A Haskell有很多對掃描,褶皺和Haskell更多好東西的很好的例子和描述。

希望這會有所幫助。

3

雖然scanl1顯然是「規範」的解決方案,它仍然是有益的,看你如何能與與foldl做到這一點:

sumList xs = tail.reverse $ foldl acc [0] xs where 
    acc (y:ys) x = (x+y):y:ys 

或者pointfree:

sumList = tail.reverse.foldl acc [0] where 
    acc (y:ys) x = (x+y):y:ys 

這裏是一個醜陋的暴力力的方法:

sumList xs = reverse $ acc $ reverse xs where 
    acc [] = [] 
    acc (x:xs) = (x + sum xs) : acc xs 

有使用一個可愛的(但不是很高性能的)解決方案:

sumList xs = tail $ map sum $ inits xs 

再次pointfree:

sumList = tail.map sum.inits 
+0

@ sepp2k:如果從列表右側開始,如何獲得剩餘元素的總和? – Landei 2011-01-19 08:21:20

0

相關的另一個問題,我發現這種方式:

rsum xs = map (\(a,b)->a+b) (zip (0:(rsum xs)) xs) 

我認爲它甚至相當有效率。