Haskell - counting the number of times each individual item in a list occurs

I'm new to Haskell and just trying to write a list comprehension to calculate the frequency of each individual value in the list, but I am having problems with the last part.

So far I have this:

frequency :: Eq a => [a] -> [(Int,a)] frequency list = [(count y list,y) | y <- rmdups ] 

Something is wrong with the last part related to rmdups.

The count function takes a character and then a list of characters and tells you how often this character occurs, the code is as follows.

 count :: Eq a => a -> [a] -> Int count x [] = 0 count x (y:ys) | x==y = 1+(count x ys) | otherwise = count x ys 

Thanks in advance.

+9
haskell
source share
7 answers

You can also use an associative array / destination map to store associations from list items to their number when calculating frequencies:

 import Data.Map (fromListWith, toList) frequency :: (Ord a) => [a] -> [(a, Int)] frequency xs = toList (fromListWith (+) [(x, 1) | x <- xs]) 

Usage example:

 > frequency "hello world" [(' ',1),('d',1),('e',1),('h',1),('l',3),('o',2),('r',1),('w',1)] 

See the documentation from fromListWith and toList .

+13
source share

I had to use Ord instead of Eq due to using sort

 frequency :: Ord a => [a] -> [(Int,a)] frequency list = map (\l -> (length l, head l)) (group (sort list)) 
+10
source share

As requested, here is a solution using Control.Arrow :

 frequency :: Ord a => [a] -> [(Int,a)] frequency = map (length &&& head) . group . sort 

This is the same function as ThePestest answer except

 λ fgl -> (fl, gl) 

replaced by

 -- simplified type signature (&&&) :: (a -> b) -> (a -> c) -> a -> (b, c) 

from Control.Arrow . If you want to avoid importing,

 liftA2 (,) :: Applicative f => fa -> fb -> f (a, b) 

also works (using instance Applicative (->) r )

+6
source share

Assuming rmdups is of type

 rmdups :: Eq a => [a] -> [a] 

Then you are missing a parameter for it.

 frequency :: Eq a => [a] -> [(Int,a)] frequency list = [(count y list,y) | y <- rmdups list] 

But the error you get will be useful in diagnosing.

+4
source share

Your rmdups function is nub from Data.List .

0
source share

Replacing rmdups with a nub list worked for me like a charm.

0
source share

Hahahaha have rmdups on pg. 86 of Programming at Haskell by Graham Hutton. It is perfect and recursive. It is also convenient in many situations.

Here is my single line rmdups which gives the same results as nub or Hutton's.

 rmdups ls = [d|(z,d)<- zip [0..] ls,notElem d $ take z ls] 

It can be used to count individual elements of the list.

 dl = "minimum-maximum" [ (d,sum [1|x<-dl,d == x]) | d<-rmdups dl] 

[('T', 6), ('I', 3), ('N', 1), ('and', 2), ('-', 1), ('a', 1), ( 'x', 1)]

0
source share

All Articles