繁体   English   中英

递归使用 haskell 返回列表

[英]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.

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