簡體   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