Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell - Most frequent value

how can i get the most frequent value in a list example:

[1,3,4,5,6,6] -> output 6
[1,3,1,5] -> output 1

Im trying to get it by my own functions but i cant achieve it can you guys help me?

my code:

del x [] = []
del x (y:ys) = if x /= y 
            then y:del x y 
            else del x ys



obj  x []= []
obj  x (y:ys) = if x== y then y:obj x y else(obj  x ys)

tam [] = 0
tam (x:y) = 1+tam  y

fun (n1:[]) (n:[]) [] =n1
fun (n1:[]) (n:[]) (x:s) =if (tam(obj x (x:s)))>n then fun (x:[]) ((tam(obj x (x:s))):[]) (del x (x:s)) else(fun (n1:[]) (n:[]) (del x (x:s))) 

rep (x:s) = fun  (x:[]) ((tam(obj x (x:s))):[]) (del x (x:s))
like image 434
Urah Avatar asked Dec 12 '12 04:12

Urah


2 Answers

Expanding on Satvik's last suggestion, you can use (&&&) :: (b -> c) -> (b -> c') -> (b -> (c, c')) from Control.Arrow (Note that I substituted a = (->) in that type signature for simplicity) to cleanly perform a decorate-sort-undecorate transform.

mostCommon list = fst . maximumBy (compare `on` snd) $ elemCount
      where elemCount = map (head &&& length) . group . sort $ list

The head &&& length function has type [b] -> (b, Int). It converts a list into a tuple of its first element and its length, so when it is combined with group . sort you get a list of each distinct value in the list along with the number of times it occurred.


Also, you should think about what happens when you call mostCommon []. Clearly there is no sensible value, since there is no element at all. As it stands, all the solutions proposed (including mine) just fail on an empty list, which is not good Haskell. The normal thing to do would be to return a Maybe a, where Nothing indicates an error (in this case, an empty list) and Just a represents a "real" return value. e.g.

mostCommon :: Ord a => [a] -> Maybe a
mostCommon [] = Nothing
mostCommon list = Just ... -- your implementation here

This is much nicer, as partial functions (functions that are undefined for some input values) are horrible from a code-safety point of view. You can manipulate Maybe values using pattern matching (matching on Nothing and Just x) and the functions in Data.Maybe (preferable fromMaybe and maybe rather than fromJust).

like image 59
huon Avatar answered Oct 25 '22 21:10

huon


In case you would like to get some ideas from code that does what you wish to achieve, here is an example:

import Data.List (nub, maximumBy)
import Data.Function (on)

mostCommonElem list = fst $ maximumBy (compare `on` snd) elemCounts where
    elemCounts = nub [(element, count) | element <- list, let count = length (filter (==element) list)]
like image 39
ljedrz Avatar answered Oct 25 '22 19:10

ljedrz