Most occurred within a list

泄露秘密 提交于 2020-05-13 14:17:54

问题


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.


回答1:


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.




回答2:


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.




回答3:


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




回答4:


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


来源:https://stackoverflow.com/questions/10181601/most-occurred-within-a-list

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!