Grouping duplicates
Haskell gurus. Care to show me some more haskellian ways to perform this task that isn't restricted by my limited knowledge of haskell and FP in general?
groupDups [] = []
groupDups list@(x:xs) = groupDups' x list
where groupD开发者_JAVA技巧ups' _ [] = []
groupDups' x list = let (m,r) = partition (x ==) list
in m : groupDups r
> groupDups [1,2,3,4,1,2,3,4,4,3,2,1,4,3,2,1]
[[1,1,1,1],[2,2,2,2],[3,3,3,3],[4,4,4,4]]
You could sort
the list, then group
it:
> import Data.List
> (group . sort) [1,2,3,4,1,2,3,4,4,3,2,1,4,3,2,1]
[[1,1,1,1],[2,2,2,2],[3,3,3,3],[4,4,4,4]]
If you want to avoid introducing an Ord
constraint in the type you can use this:
import Data.List
groupDups [] = []
groupDups (x:xs) = (x : group) : groupDups xs' where
(group,xs') = partition (==x) xs
It's correspondingly slower than (group . sort)
and groups are ordered by first occurrence in the original list:
*Main> groupDups [1,3,2,3,4,1,2,3,4,4,3,2,1,4,3,2,1]
[[1,1,1,1],[3,3,3,3,3],[2,2,2,2],[4,4,4,4]]
You might be able to improve complexity slightly by making a helper function that accumulates into a parameter list, ask if you're interested in the details.
Here is something weird to do this.
groupDups ls =
map (\(h:t) -> t) $ foldl (\s e -> map (\(h:t) -> if h == e then (e:h:t) else (h:t)) s) (nub [[x] | x <- ls]) ls
This function requires only Eq
groupDups xs = foldl insert [] xs
where insert [] x = [[x]]
insert (ys@(y:_):yss) x | x == y = (x:ys):yss
| otherwise = ys:(insert yss x)
精彩评论