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