fuuman
fuuman

Reputation: 461

Finding list entry with the highest count

I have an Entry data type

data Entry = Entry {
    count :: Integer,
    name :: String }

Then I want to write a function, that takes the name and a list of Entrys as arguments an give me the Entrys with the highest count. What I have so far is

searchEntry :: String -> [Entry] -> Maybe Integer
searchEntry _ [] = Nothing
searchEntry name1 (x:xs) = 
   if name x == name1
       then Just (count x)
       else searchEntry name xs 

That gives me the FIRST Entry that the function finds, but I want the Entry with the highest count. How can I implement that?

Upvotes: 0

Views: 151

Answers (3)

jamshidh
jamshidh

Reputation: 12060

I would consider changing the signature of the function to String->Maybe Entry (or String->[Entry]) if you indeed want to return the "Entry" items with the highest count.

Otherwise, you can actually do what you want as a oneliner using some pretty common Haskell functions....

As Bheklilr mentioned, the name filter can be done first, and it is really easy to do this using the filter function....

filter (hasName theName) entries

Note that hasName can be written out fully as a separate function, but Haskell also offers you the following shortcut.

hasName = (== theName) . name

Now you just need the maximum value.... Haskell has a maximum function, but it only works on the Ord class. You can make Entry an instance of Ord, or you can just use the related maximumBy function, that takes an extra ordering function

maximumBy orderFunction entries2

Again, you can write orderFunction yourself (which you might want to do as an excercise), but haskell again offers a shortcut.

orderFunction = compare `on` count

You will need to import some libs to get this all to work (Data.Function, Data.List). You also will need to put in some extra code to account for the Nothing case.

It might be worth it to write out the functions longhand first, but I recommend that you use Hoogle to lookup and understand compare, on, and maximumBy.... Using tricks like this can really shorten your code.

Putting it all together, you can get the entry with the maximum count like this

maxEntry = maximumBy (compare `on` count) $ filter ((theName ==) . name) $ entries

You will need to modify this to account for the Nothing case, or if you want to return all max Entries (this just chooses one), or if you really wanted to return count, and not the entry.

Upvotes: 0

bheklilr
bheklilr

Reputation: 54058

My suggestion would be to break the problem into two parts:

  1. Find all entries matching a given name
  2. Find the entry with the highest count

You could set it up as

entriesByName :: String -> [Entry] -> [Entry]
entriesByName name entries = undefined

-- Use Maybe since the list might be empty
entryWithHighestCount :: [Entry] -> Maybe Entry
entryWithHighestCount entries = undefined

entryByNameWithHighestCount :: String -> [Entry] -> Maybe Entry
entryByNameWithHighestCount name entires = entryWithHighestCount $ entriesByName name entries

All you have to do is implement the relatively simple functions that are used to implement getEntryByNameWithHighestCount.

Upvotes: 4

Guvante
Guvante

Reputation: 19203

You need to add an inner method that takes a current result as a parameter and returns that instead of Nothing when reaching the end of the method.

Also you would need to update your result found logic to compare a potentially existing function and the found value.

Upvotes: 0

Related Questions