Snikcers
Snikcers

Reputation: 13

Counting the occurrences of chararacters in a string

I got the task to count the number of occurrences of each (lower case) character in a string. I am not allowed to use any function of the library, I came up with the following, working solution.

occur :: String -> [(Char,Int)]
occur y =  [ (x,count x y) | x<-['a'..'z'],  count x y > 0]

I was trying at first:

occur2 :: String -> [(Char,Int)]
occur2 y =  [ (x,z) | x<-['a'..'z'], z<- count x y,  count x y > 0]

I defined the helper function count like this:

count :: Char -> String -> Int
count k str = length [n | n <- str, n == k]

Two questions:

  1. Why is occur2 not working?
  2. Is there any way to define occur without my aux function count?

Upvotes: 1

Views: 103

Answers (1)

castletheperson
castletheperson

Reputation: 33466

occur2 isn't working because count x y is not a list, so it can't be used for a generator expression like in z <- count x y. Instead, use a let expression.

You can remove the count definition by inlining it.

occur :: String -> [(Char,Int)]
occur y = [ (x,z) | x <- ['a'..'z'], let z = length [n | n <- y, n == x], z > 0]

If you were to use libraries, a simple and efficient implementation would be to use a MultiSet.

import qualified Data.MultiSet as MS

occur :: String -> [(Char,Int)]
occur = MS.toAscOccurList . MS.fromList . filter (\c -> c >= 'a' && c <= 'z')

Upvotes: 2

Related Questions