編寫一個返回列表運行總和的函數。例如運行[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)
編寫一個返回列表運行總和的函數。例如運行[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)
您可以調整功能,通過簡單地在前面加上a+x
對每個步驟的結果,並使用空列表作爲基礎的情況下,產生一個列表:
sumlist' xx = aux xx 0
where aux [] a = []
aux (x:xs) a = (a+x) : aux xs (a+x)
然而,它是更地道的Haskell來表達這種作爲摺疊或掃描的東西。
我想你想的scanl1和組合(+),所以像
scanl1 (+) *your list here*
scanl1將應用給定函數跨名單,並報告每一箇中間值到返回的列表。
一樣,寫出來的僞代碼,
scanl1 (+) [1,2,3]
將輸出就像一個列表:
[1, 1 + 2, 1 + 2 + 3]
,或者換句話說,
[1, 3, 6]
Learn You A Haskell有很多對掃描,褶皺和Haskell更多好東西的很好的例子和描述。
希望這會有所幫助。
雖然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
相關的另一個問題,我發現這種方式:
rsum xs = map (\(a,b)->a+b) (zip (0:(rsum xs)) xs)
我認爲它甚至相當有效率。
@ sepp2k:如果從列表右側開始,如何獲得剩餘元素的總和? – Landei 2011-01-19 08:21:20