將串列分成子串列:將相同的值添加到一個子串列中,將不同的值添加到另一個子串列中。它需要foldr通過串列的一次傳遞來完成,而不是使用 .
例如:
ghci> splitList [1,2,2,4,5,7,7,8,9]
[[1],[2,2],[4,5],[7,7],[8,9]]
我做了這樣的事情:
splitList :: [Int] -> [[Int]]
splitList = getRes . foldr func5 ([],False,0) where
func5 c ([],_,_) = ([[c]],False,c)
func5 c (y@(x:xs), b, l) | c == l = ((c:x):xs, False, c)
| b = ((c:x):xs, False, c)
| otherwise = ([c]:y, True, c)
getRes :: ([[Int]], Bool, Int) -> [[Int]]
getRes (a,_,_) = a
但它并沒有像我預期的那樣作業......
ghci> splitList [1,2,2,4,5,7,7,8,9]
[[1],[2,2],[4,5],[7,7,8],[9]]
uj5u.com熱心網友回復:
既然你正在使用foldr,
> splitList [1,2,2,4,5,7,7,8,9]
[[1],[2,2],[4,5],[7,7],[8,9]]
應該從右邊作業
> splitList [1,2,2,4,5,7,7,8,9]
[]
[[9]]
[[8,9]]
[[7,8,9]]
[[7,7],[8,9]]
[[5],[7,7],[8,9]]
[[4,5],[7,7],[8,9]]
[[2,4,5],[7,7],[8,9]]
[[2,2],[4,5],[7,7],[8,9]]
[[1],[2,2],[4,5],[7,7],[8,9]]
現在剩下的就是在代碼中寫下來。
從上面可以明顯看出,我們只需要將當前元素與“累加器”的頭部進行比較(除了特殊情況下無條件收集的串列的最后兩個元素),同時保持“相同”標志。所以可以編碼為
splitList :: Eq a => [a] -> [[a]]
splitList xs = snd $ foldr g (undefined,[]) xs
where
g x (b,[]) = (b,[[x]])
g x (_,[y]:t) = (x==y,[x,y]:t)
g x (b,(a:r):t)
| (x==a)==b = (b,(x:a:r):t)
| otherwise = (not b, if b then [x]:(a:r):t
else [x,a]:r:t)
測驗:
> splitList [1,2,2,4,5,7,7,8,9]
[[1],[2,2],[4,5],[7,7],[8,9]]
> splitList [1,2,2,4,5,7,7,8,9,9]
[[1],[2,2],[4,5],[7,7],[8],[9,9]]
> splitList [1,2,2,4,5,7,8,9,9,9]
[[1],[2,2],[4,5,7,8],[9,9,9]]
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/366334.html
