计算Haskell中的列表累积和

时间:2011-01-19 06:13:40

标签: haskell

编写一个返回列表运行总和的函数。例如运行[1,2,3,5]是[1,3,6,11]。我在下面编写这个函数,它可以返回列表中所有值的最终总和。那我怎么能逐个分开它们呢?

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

5 个答案:

答案 0 :(得分:29)

我认为您需要scanl1(+)的组合,所以类似

scanl1 (+) *your list here*

scanl1将在列表中应用给定的函数,并将每个中间值报告给返回的列表。

喜欢,用伪代码写出来,

scanl1 (+) [1,2,3]

会输出如下列表:

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

或换句话说,

[1, 3, 6]

Learn You A Haskell有很多很好的例子和描述扫描,折叠以及更多Haskell的好东西。

希望这有帮助。

答案 1 :(得分:9)

您可以通过简单地将a+x添加到每个步骤的结果并使用空列表作为基本案例来调整您的函数以生成列表:

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

然而,更为惯用的Haskell将这种事物表达为折叠或扫描。

答案 2 :(得分:4)

虽然scanl1显然是“规范”解决方案,但看看你如何用foldl做这件事仍然是有益的:

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

或点免费:

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

使用inits

有一个可爱(但不是非常高效)的解决方案
sumList xs = tail $ map sum $ inits xs

再次点免费:

sumList = tail.map sum.inits

答案 3 :(得分:1)

与我发现的另一个问题相关:

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

我认为它甚至非常有效。

答案 4 :(得分:0)

我不确定这有多规范,但对我来说它看起来很漂亮:)

sumlist' [] = []
sumlist' (x:xs) = x : [x + y | y <- sumlist' xs]