[英]Recursion returning a list of list using haskell
我对 Haskell 很陌生,我不知道如何解决/解决这个问题:我想要一个带有类型签名的 function: [((Double, Double), Bool)]
-> [[(Double, Double)]]
。 如果Bool == True
,则 function 应仅将(Double, Double)
添加到列表列表中。 如果 bool 为 False,我希望将与下一个 True bool 关联的(Double, Double)
添加到新列表中。 与Bool == True
配对的连续(Double, Double)
应该添加到同一个列表中。 例如,输入: [((1,1),True),((2,2), False),((3,3), False),((4,4),True),((5,5),True)]
应该返回[[(1,1)],[(4,4),(5,5)]]
。 我做了一些研究,似乎 groupBy function 可能有助于解决问题,但我不太确定如何正确使用它。 由于我是 Haskell 的新手,我更喜欢更简单的解决方案或解释,但任何建议都会有所帮助。
到目前为止,我的代码只是为与 True bool 关联的每个(Double, Double)
创建了一个新列表。 我不太确定如何添加到列表中的现有列表。
consecTrue :: [((Double, Double),Bool)] -> [[(Double,Double)]]
consecTrue xs = case xs of
[] -> []
x:xs
|snd x == True -> [fst x]:consecTrue xs
|snd x == False -> consecTrue xs
是的,可以使用 groupBy。 您将需要比较 function 来提供 groupBy,我们称之为grf
。 最简单的方法可能是在交互式命令ghci
中逐步测试解决方案。
$ ghci
Prelude>
Prelude Data.List> import Data.List
Prelude Data.List> grf ((x1,y1),p1) ((x2,y2),p2) = (p1==p2)
Prelude Data.List> let lsa = [((1,1),True),((2,2), False),((3,3), False), ((4,4),True),((5,5),True)]
Prelude Data.List>
Prelude Data.List> lsb = groupBy grf lsa
Prelude Data.List> lsb
[[((1,1),True)],[((2,2),False),((3,3),False)],[((4,4),True),((5,5),True)]]
Prelude Data.List>
这只是一个开始。 然后你需要摆脱虚假的,然后摆脱 boolean 值本身。
Prelude Data.List>
Prelude Data.List> lsc = filter (snd . head) lsb
Prelude Data.List> lsc
[[((1,1),True)],[((4,4),True),((5,5),True)]]
Prelude Data.List>
Prelude Data.List> lsd = map (map fst) lsc
Prelude Data.List> lsd
[[(1,1)],[(4,4),(5,5)]]
Prelude Data.List>
Prelude Data.List>
把它们放在一起:
import Data.List
consecTrue :: [((Double, Double),Bool)] -> [[(Double,Double)]]
consecTrue xs = let grf ((x1,y1),p1) ((x2,y2),p2) = (p1==p2)
in map (map fst) (filter (snd . head) (groupBy grf xs))
main = do
let lsa = [((1,1),True),((2,2), False),((3,3), False),
((4,4),True),((5,5),True)]
let res = consecTrue lsa
putStrLn $ "input = " ++ show lsa
putStrLn $ "output = " ++ show res
这似乎做你想要的:
input = [((1.0,1.0),True),((2.0,2.0),False),((3.0,3.0),False),((4.0,4.0),True),((5.0,5.0),True)]
output = [[(1.0,1.0)],[(4.0,4.0),(5.0,5.0)]]
作为一个学习 Haskell 的新手,甚至还不知道map
是什么,首先通过简单、直接的递归来创建一个独立的定义,而不使用任何库函数,这是完全有意义的。
简单直接递归的定义只是列举我们遇到的可能情况:
consecTrue :: [(t, Bool)] -> [[t]]
-- empty list:
consecTrue [] = []
-- list with exactly one entry in it:
consecTrue [(a,True)] = [[a]]
consecTrue [(a,False)] = []
-- list with two or more entries in it:
consecTrue ((a1,True) : (a2, True) : more2) = (a1:r):q where
(r:q) = consecTrue ((a2,t2) : more2)
consecTrue ((a1,True) : (a2,False) : more2) = [a1] : consecTrue more2
consecTrue ((a1,False) : more1) = consecTrue more1
(Double, Double)
是无关紧要的、无关紧要的细节。 只要t
就足够了,这意味着任何东西都可以 go 在那里。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.