我將找到解決此問題的方法:
將給定串列拆分為具有給定子串列長度和跳過長度的子串列,例如:
groupEvery 3 1 [1..6] = [[1,2,3], [2,3,4], [3,4,5], [4,5,6]]
groupEvery 3 2 "abcdefghij" = [ "abc", "cde", "efg", "ghi", "ij"]
groupEvery n p l引數詳細資訊是:
- n 是子串列的長度:Int
- f 是跳過的長度:Int
- xs 是輸入串列:[a]
這是我的解決方案:
groupEvery :: Int -> Int -> [a] -> [[a]] -> [[a]]
groupEvery n p xs acc
| length xs <= n = acc [xs]
| otherwise = groupEvery n p dropped (acc [segment])
where
dropped = drop p xs
segment = take n xs
但是這個解決方案并不懶惰,例如take 3 Lib2.groupEvery 3 1 [1..] []從未完成。我的問題是關于
- 更好的
groupEvery功能解決方案? - 我們如何撰寫累積一些資料的遞回惰性函式?換句話說,這種累積結果并且是惰性的遞回函式是否有任何結構?
uj5u.com熱心網友回復:
主要問題是您使用累加器并且僅在遍歷整個輸入串列時才回傳串列。此外length l將遍歷整個串列。你不需要計算長度。這也是低效的:如果串列很長,它每次都會進行線性運行。
您可以在串列上進行模式匹配,對于空串列,回傳一個空串列,對于非空串列,產生take n xs并遞回使用drop p xs.
groupEvery :: Int -> Int -> [a] -> [[a]]
groupEvery _ _ [] = []
groupEvery n p xs = take n xs : groupEvery n p (drop p xs)
因此,這會產生:
ghci> take 3 (groupEvery 3 1 [1..])
[[1,2,3],[2,3,4],[3,4,5]]
take n您可以通過組合和進一步改進該功能,drop p這樣您只需遍歷min n p串列的各個部分一次。我把它留作練習。
uj5u.com熱心網友回復:
您在這里對“累加器”的使用含糊不清。
有用的命名法是“狀態傳遞和建立”、“輸出串列創建”、“尾遞回”和“保護遞回”,在嚴格設定中也稱為“尾遞回模 cons”。
是的,我們可以通過受保護的遞回逐步創建輸出串列,同時安排從一個呼叫到下一個呼叫的傳遞和累積/建立狀態:
makeList elt next state = go state
where
go state = elt state : go (next state)
--- which is just
-- go = map elt . iterate next
(“受保護的”遞回,由惰性資料建構式保護,here :)。
具體來說,您的示例是
groupEvery n p = makeList (take n) (drop p)
直至終止條件:
> takeWhile (not . null) $ groupEvery 3 2 [1..20]
[[1,2,3],[3,4,5],[5,6,7],[7,8,9],[9,10,11],[11,12,13],
[13,14,15],[15,16,17],[17,18,19],[19,20]]
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/425227.html
上一篇:不保留內容的串列串列
下一篇:串列上的遞回除法
