2014-02-24 32 views
2

我有一个名为Person代数数据类型如下:查找基于数据字段的数据哈斯克尔

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

我也有Person充满了对人的各种信息的列表,现在说我要回所有一个具体Person的数据基于firstName单独,我该怎么做?

像通过存储在列表中的所有firstName的搜索,然后返回如果查询匹配要么Just PersonNothing如果没有任何匹配

回答

4

您可以使用filter返回一个包含所有列表PersonfirstName上给出的条件。

例如:

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

其中xs包含Person列表。如果没有Person匹配条件,这将返回一个空列表([])。

+1

如果你只在第一场比赛有兴趣,你可以用' Data.Maybe.listToMaybe'在被过滤的列表上。 – raymonad

+2

...或者你可以使用'Data.List.find'。 – kosmikus

1

很简单,你可以写一个自定义的查找功能:

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 

然后,你可以使用它作为

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 

这将打印

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}) 

(假设它编译,我没有运行这个代码,但它应该工作)。


如果你想你是否得到一个单一的项目或匹配的项目列表中进行选择,你可以做

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