0

How would I remove unique elements in a list, so only frequently occurring elements remain, (only using prelude functions). for example

["abc","abc","a","b","c","b"]

would return:

["abc","b"]

In the case that all elements occur exactly once, all would be returned.

If it helps, I have already implemented a sort function.

Arthur
  • 347
  • 1
  • 4
  • 14

3 Answers3

2

How about this?

import Data.List

getDups :: Ord a => [a] -> [a]
getDups = map head . filter (\l -> length l > 1) . group . sort

First you sort the list because group only works when the same elements are adjacent. Then you filter the groups that have more than one element. That you take the first element of each group because you already know there is at least one.

DiegoNolan
  • 3,766
  • 1
  • 22
  • 26
  • Thats very helpful, however is there anyway of doing this without using group, considering I need to use only prelude functions? If not, I suppose I can try to implement it. – Arthur Dec 16 '14 at 23:19
1

After you sort, you can pattern match on repeat elements, dropping everything else.

dropSingles [] = []
dropSingles (x:y:rest) | x == y = x:dropSingles (dropWhile (== x) rest)
dropSingles (x:rest) = dropSingles rest 
jamshidh
  • 12,002
  • 17
  • 31
  • @DiegoNolan- my bad, thanks for the catch. It has been fixed. – jamshidh Dec 16 '14 at 23:44
  • The filter part does not do what I want. It just removes list elements with single characters, not removing list elements which occur only once. – Arthur Dec 17 '14 at 09:53
  • Thanks, could you explain what the last line does? – Arthur Dec 17 '14 at 11:09
  • @Arthur- basically, it actually drops the single.... The doubles case was already matched up above, so this is the default, it matches against a single, then ignores the value `x` just matched and recursively drops singles on the rest. – jamshidh Dec 17 '14 at 16:36
1
import Data.List

f xs = case nub (xs \\ nub xs) of
    []  -> xs
    xs' -> xs'

main = do
    print $ f ["abc","abc","abc","a","b","c","b"] -- ["abc","b"]
    print $ f ["abc","a","c","b"]                 -- ["abc","a","c","b"]

I.e. remove each element once and then return each element once.

effectfully
  • 12,325
  • 2
  • 17
  • 40