简体   繁体   English

Haskell - 在列表中累计的总和

[英]Haskell — Sums Accumulated in Lists

I need to create or know if there is a function in Haskell that allows you to add items from a list. 我需要创建或知道Haskell中是否有一个函数允许您从列表中添加项目。 So, for example: 所以,例如:

cumulativeAmount :: [Integer] -> [Integer]

cumulativeAmount [1,2,5,8,8,0,4,2] = [1,3,8,16,24,24,28,30]

cumulativeAmount [1,4,7,0,5] = [1, 1+4, 1+4+7, 1+4+7+0, 1+4+7+0+5] = [1,5,12,12,17]

I tried to use the map and scanl function, but I didn't get what I wanted, because I added all the elements. 我试图使用mapscanl函数,但是我没有得到我想要的东西,因为我添加了所有元素。

This is exactly the purpose of scanl1 :: (a -> a -> a) -> [a] -> [a] : 这正是scanl1 :: (a -> a -> a) -> [a] -> [a]

Prelude> scanl1 (+) [1,2,5,8,8,0,4,2]
[1,3,8,16,24,24,28,30]

scanl1 takes as input a function f :: a -> a -> a (here (+) ), and a list of a s. scanl1将函数f :: a -> a -> a (here (+) )和s的列表作为a It constructs a list where the first item is the first item of the list. 它构造一个列表,其中第一个项目是列表的第一个项目。 This is the first value of the accumulator . 这是累加器的第一个值。 Then for every value, the accumulator is updated by calling f with the accumulator and the next value of the list, this item is then yielded. 然后对于每个值,通过使用累加器和列表的下一个值调用f来更新累加器,然后生成该项。

So in case of scal1 (+) [1,2,5] the first item we emit is 1 , we also set the accumulator to 1 . 因此,在scal1 (+) [1,2,5]的情况下,我们发出的第一个项是1 ,我们还将累加器设置为1 The next item is 2 , so we call (+) 1 2 (which is 3 ) and this is the result and the new accumulator, next we call (+) ((+) 1 2) 5 (which is 8 ), etc. 下一个项目是2 ,所以我们调用(+) 1 2 (这是3 )这是结果和新的累加器,接下来我们调用(+) ((+) 1 2) 5 (这是8 )等。

But I think it is better, as an exercise to use recursion. 但我认为这更好,作为使用递归的练习。 Like said before we use an accumulator. 就像之前我们使用累加器一样。 We can implement this by introducing an extra function where the accumulator is a function we pass through the recursive calls (and update). 我们可以通过引入一个额外的函数来实现它,其中累加器是我们通过递归调用(和更新)的函数。 So in that case it looks like: 所以在这种情况下它看起来像:

cumulativeAmount :: [Integer] -> [Integer]
cumulativeAmount [] = ...
cumulativeAmount (x:xs) = go x xs
    where go x xs = ...

so here the first argument of go ( x ) is the accumulator. 所以这里gox )的第一个参数是累加器。 I leave it as an exercise to implement it with recursion. 我把它留作练习用递归来实现它。

What about using an accumulator: 使用累加器怎么样:

cumulativeAmount :: (Num a) => [a] -> [a]
cumulativeAmount xs = go xs 0
    where go [] acc = []
          go (x:xs) acc = (acc+x) : go xs (acc+x)

Which works as follows: 其工作原理如下:

*Main> cumulativeAmount [1,2,5,8,8,0,4,2]
[1,3,8,16,24,24,28,30]

The above code keeps a state variable acc to accumulate sums whenever a new number is encountered, and adds the new sum to the resulting list. 上面的代码保持状态变量acc以便在遇到新数字时累加和,并将新总和添加到结果列表中。

Now a good exercise would be to replace the above code with higher order functions. 现在,一个很好的练习是用更高阶函数替换上面的代码。

在我的头顶,您可以通过列表理解来解决这个问题,如下所示:

cumulativeAmount xs = [ sum $ take x xs | x <- [1..length xs] ]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM