作為一項編程練習,我試圖在 Haskell 中構建一個函式,在給定串列的情況下,只要重復一個元素,它就會拆分串列。例如, [1,2,3,3,4,5] 將拆分為 [[1,2,3],[3,4,5]]。我的第一個想法是將串列拆分為具有單個元素的串列串列,其中 [1,2,3,3,4,5] 將變為 [[1],[2],[3],[3], [4],[5]] 然后僅在被比較的元素不相等時才合并串列,但是實作這對我來說一直很頭疼,因為我對 Haskell 很陌生,遞回總是給我帶來麻煩。我認為我用來組合串列的函式有問題,它只會回傳一個串列,其中所有被分解的元素都被組合在一起,其中 [1,2,3,3,4,5] 變為[[1],[2],[3],[3],[4],[5]] 但我的 split_help 函式會將其轉換為 [[1,2,3,3,4,5]] 而不是[[1,2,3],[3,4,
我在下面粘貼了我不完整的代碼,它現在不起作用,但它應該讓我大致了解我想要完成的作業。任何關于一般 Haskell 代碼禮儀的反饋也將受到歡迎。
split_breaker 將串列分解為串列串列,而 split_help 是我試圖用來組合不相等元素的方法。
split_help x y
| x /= y = x y
| otherwise = []
split_breaker :: Eq a => [a] -> [[a]]
split_breaker [] = []
split_breaker [x] = [[x]]
split_breaker (x:xs) = [x]:split_breaker xs
split_at_duplicate :: Eq a => [a] -> [[a]]
split_at_duplicate [x] = [[x]]
split_at_duplicate (x:xs) = foldl1 (split_help) (split_breaker [xs])
uj5u.com熱心網友回復:
你想像這樣作業嗎?
splitAtDup [1,2,3,3,3,4,4,5,5,5,5,6]
[[1,2,3],[3],[3,4],[4,5],[5],[5],[5,6]]
我對嗎?
然后簡單地做:
splitAtDup :: Eq a => [a] -> [[a]]
splitAtDup (x : y : xs) | x == y = [x] : splitAtDup (y : xs)
splitAtDup (x : xs) =
case splitAtDup xs of
x' : xs' -> (x : x') : xs'
_ -> [[x]]
splitAtDup [] = []
uj5u.com熱心網友回復:
這是一個最大懶惰的方法:
splitWhen :: (a -> a -> Bool) -> [a] -> [[a]]
splitWhen f = foldr go [[]] where
go x acc = (x:xs):xss where
xs:xss = case acc of
(z:_):_ | f x z -> []:acc
_ -> acc
splitAtDup :: Eq a => [a] -> [[a]]
splitAtDup = splitWhen (==)
要驗證惰性,請嘗試以下操作:
take 2 $ take 4 <$> splitAtDup (1:2:3:3:4:5:6:undefined)
它可以完全評估為范式,如[[1,2,3],[3,4,5,6]]。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/424342.html
上一篇:獲取陣列前綴中的主導元素
