ErHunt
ErHunt

Reputation: 311

Most occurred within a list

I have a high order function which would take:

results ["Red", "Blue", "Green", "Blue", "Blue", "Red"]

And return:

[(1,"Green"),(2,"Red"),(3,"Blue")]

I need to use the results function and create a new function called winner:

winner :: [Party ] -> Party
winner xs = 

which would output the most occurred colour and remove first element within tuples, if two colours have the same occurrences it output two the colours, for example:

winner ["Red", "Blue", "Green", "Blue", "Blue", "Red"]

output:

"blue"

so far I've tried using snd and tail but I keep getting errors. Thank you in advance.

Upvotes: 2

Views: 3060

Answers (4)

Landei
Landei

Reputation: 54574

If you want to avoid sorting, you could use a MultiSet, which has a finMax function.

Upvotes: 3

none
none

Reputation: 51

import Data.List
import Data.Ord
winner xs = head . maximumBy (comparing length) . group . sort $ xs
main = print  $ winner ["Red", "Blue", "Green", "Blue", "Blue", "Red"]

looks like the most direct way.

Upvotes: 5

Daniel Fischer
Daniel Fischer

Reputation: 183858

If you have the results function, a simple application of

maximumBy :: (a -> a -> Ordering) -> [a] -> a

would suffice

import Data.List -- for maximumBy
import Data.Ord  -- for comparing

winner = snd . maximumBy (comparing fst) . results

Seeing

if two colours have the same occurrences it output two the colours

you need a different type - and of course a different implementation, still easy with library functions, though:

import Data.List
import Data.Ord
import Data.Function

winners :: [Party] -> [Party]
winners = map snd . head . groupBy ((==) `on` fst) . sortBy (flip $ comparing fst) . results

Since results already produces a sorted list - I didn't want to rely on that just from the example output - it is not necessary to sort again, and we can use

winners = map snd . last . groupBy ((==) `on` fst) . results

to produce the list of all most occurring elements. If only one most frequent element is desired, it could be obtained with

winner = snd . last . results

from the sorted frequency list.

Upvotes: 10

Boris
Boris

Reputation: 5176

In the winners function, you get the list of String, which you can then transform into a list of ´(Int, String)´ tuples by applying the results function. You then want to take the last of those tuples (assuming that results returns the elements in ascending order of number of occurrences) and return the second element of that tuple. You already mention that you have tried the snd function, so the only trouble is with the middle step, getting the last element of the list of tuples, correct?

What should be the type of the function that returns that last element? It takes a list of (Int, String) tuples and returns a single tuple, so one guess at the type could be [(Int, String)] -> (Int, String), but the function doesn't really need to know that it is dealing with tuples inside the list. It just needs to return the last element of a list, so a better type might be [a] -> a. Armed with this type, go to Hoogle and type it in the search box, and you get the function you need as the second result.

This should suffice for a winners function that only returns a single result. If you want to be able to return more than one result, then - as Daniel Fischer notes in his answer - you need another signature and a slightly more complex implementation. I think the simplest thing would be to find all the tuples which have the same occurrence as the last tuple (again assuming ascending order of occurrences) by filtering out those tuples which don't have the maximum number of occurrences, and then convert the resulting list of tuples to a list of the second elements of those tuples, by mapping snd over the list:

winners :: [String] -> [String]
winners xs = map snd maxOccursTuples
    where maxOccursTuples = filter isMaxOccursTuple occurrences
          isMaxOccursTuple tuple = fst tuple == maxOccurs
          maxOccurs = fst (last occurrences)
          occurrences = results xs

Upvotes: 1

Related Questions