Reputation: 461
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 Entry
s as arguments an give me the Entry
s 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
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
Reputation: 54058
My suggestion would be to break the problem into two parts:
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
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