Electric Coffee
Electric Coffee

Reputation: 12124

Find data based on data fields haskell

I have an algebraic data type called Person looks like this:

data Person = 
   Person { firstName :: String
          , lastName  :: String
          , height    :: Float
          , age       :: Int
          } deriving (Show, Eq)

I also have a list of Person filled with various information about people, now say I want to return all the data of one specific Person based on firstName alone, how would I do that?

Like search through all the firstNames stored in the list, and then returning either Just Person if the query matches or Nothing if there isn't any match

Upvotes: 2

Views: 193

Answers (2)

bheklilr
bheklilr

Reputation: 54068

Very simply, you could write a custom lookup function:

lookupBy :: Eq b => (a -> b) -> [a] -> b -> Maybe a
lookupBy _ [] _ = Nothing
lookupBy f (x:xs) key = if f x == key then Just x else lookupBy f xs key

Then you could use it as

main = do
    let people = [Person "John" "Doe" 68 30, Person "Jane" "Smith" 63 28]
    print $ lookupBy firstName people "Jane"
    print $ lookupBy lastName  people "Doe"
    print $ lookupBy age       people 29
    print $ lookupBy height    people 63

This would print

Just (Person {firstName="Jane", lastName="Smith", height=63, age=28})
Just (Person {firstname="John", lastName="Doe", height=58, age=30})
Nothing
Just (Person {firstName="Jane", lastName="Smith", height=63, age=28})

(assuming that it compiles, I have not run this code but it should work).


If you want to choose on whether you get a single item or a list of matching items, you could do

import Data.Maybe (listToMaybe)

lookupAllBy :: Eq b => (a -> b) -> [a] -> b -> [a]
lookupAllBy f xs key = filter (\x -> f x == key) xs

lookupBy :: Eq b => (a -> b) -> [a] -> b -> Maybe a
lookupBy f xs key = listToMaybe $ lookupAllBy f xs key

Upvotes: 1

tofcoder
tofcoder

Reputation: 2382

You can use filter to return a list that contains all the Person with a given condition on firstName.

For instance:

filter (\x -> firstName x == "John") xs

where xs contains the list of Person. This will return an empty list ([]) if no Person matches the criteria.

Upvotes: 4

Related Questions