我有一个如下所示的列表:
lst = [1,2,6,3,9]
Run Code Online (Sandbox Code Playgroud)
我想编写一个函数,该函数对列表中的所有数字求和,并将此值附加到新列表,然后遍历列表并逐个删除值并对值求和.该函数将执行此计算:
result = [[1+2+6+3+9],
[1+6+3+9],
[1+2+3+9],
[1+2+6+9],
[1+2+6+3]]
Run Code Online (Sandbox Code Playgroud)
我试图描述的函数会产生这个结果给出上面的列表示例:
[21,19,15,18,12]
我很难理解如何在Haskell中实现这个功能.具体来说,如何遍历列表,并删除一个元素,但每次将删除的值增加一.有人可以帮忙吗?谢谢.我一直在尝试编写一个使用折叠的辅助函数,但我无法弄清楚如何在每次"迭代"时从最后一个元素中删除不同的元素.
m09*_*m09 12
你可以沿着这些方向写一些东西:
f xss@(x:xs) = total : map (total -) xs
where total = sum xss
Run Code Online (Sandbox Code Playgroud)
基本上它说首先你有你的列表的总和,然后你有每个元素这个相同的总和减去这个元素(我们跳过头).
更多细节:
(x:xs) 用于在给定列表上进行模式匹配,以便我们稍后可以通过仅使用来轻松跳过头部 xsxss@... 用于命名整个模式,以便我们仍然可以轻松地使用整个列表(total -)是一个运算符部分:当使用参数调用时x,它将返回total - x注意:您必须确定当此函数被赋予空列表时会发生什么,例如,如果您希望它返回空列表,请添加:
f [] = []
Run Code Online (Sandbox Code Playgroud)
编辑:解释map (total -) xs:
正如我在上面的列表中详述的那样,(total -)是一个操作符部分,它为我们提供了以下功能:
\x -> total - x
Run Code Online (Sandbox Code Playgroud)
它返回总减去它给出的值.
现在,我们将该函数映射到给定列表的尾部f.例如,如果您给出f列表
[1, 2, 6, 3, 9]
Run Code Online (Sandbox Code Playgroud)
它将我映射过来
[2, 6, 3, 9]
Run Code Online (Sandbox Code Playgroud)
如果为total 21,则地图调用的结果为
[19, 15, 18, 12] -- [21 - 2, 21 - 6, 21 - 3, 21 - 9]
Run Code Online (Sandbox Code Playgroud)
Mog给出了一个答案,它利用了(+)联想,可交换和反向的事实.但是,我认为给出适用于任何操作的答案也是有建设性的; 也就是说,为了产生你正在求和的实际列表,然后求它们.所以计划将是这样的:
Prelude:使用sum函数).第一部分还有几种方法.第一个选择是显式递归:
splits :: [a] -> [([a], [a])]
splits [] = [([],[])]
splits (x:xs) = ([],x:xs) : map (\(b,e) -> (x:b,e)) (splits xs)
Run Code Online (Sandbox Code Playgroud)
我们可以在ghci中查看它以确保我们做对了:
*Main> splits "abcde"
[("","abcde"),("a","bcde"),("ab","cde"),("abc","de"),("abcd","e"),("abcde","")]
Run Code Online (Sandbox Code Playgroud)
但是,有一个更好的方式.该Data.List模块包括一系列用于以特定方式重新排列列表的函数.其中两个是tails和inits:
*Main> tails "abcde"
["abcde","bcde","cde","de","e",""]
*Main> inits "abcde"
["","a","ab","abc","abcd","abcde"]
Run Code Online (Sandbox Code Playgroud)
所以这个定义看起来更好看:
splits xs = zip (inits xs) (tails xs)
Run Code Online (Sandbox Code Playgroud)
现在,我们想要一个生成列表列表的函数,每个位置都删除一个元素.
dropEach xs = [beginning ++ end | (beginning, ignored:end) <- splits xs]
Run Code Online (Sandbox Code Playgroud)
所以最后一步是把所有东西放在一起.
funnySums xs = map sum (xs : dropEach xs)
Run Code Online (Sandbox Code Playgroud)
我们可以测试:
*Main> funnySums [1, 10, 100, 1000, 10000]
[11111,11110,11101,11011,10111,1111]
Run Code Online (Sandbox Code Playgroud)