基本的Haskell:在多个列表中搜索相同的元素

时间:2013-10-06 14:57:25

标签: haskell

我一直在与这个问题作斗争。我正在尝试创建一个“组织”,这是一个健身房列表。这些健身房是人员名单。每个人都有身份证号码,年龄和信用额度。

我希望FindID功能搜索组织以搜索健身房列表,找到输入ID的用户,然后返回他们的信用总额。但是,我觉得我过度考虑了这个问题,现在我真的很挣扎。

newtype ID = ID Int deriving (Show)
newtype Age = Age Int deriving (Show)
newtype Credit = Credit Int deriving (Show)
newtype Person = Person (ID, Age, Weight) deriving (Show)   
type Gym = [Person]
type Organisation = [Gym]


getAge :: Person -> Int
getAge (Person(a,Age b,c)) = b

getID :: Person -> Int
getID (Person(ID a,b,c)) = a

getCredit :: Person -> Int
getCredit (Person(a,b,Credit c)) = c

p = Person ( ID 123, Age 65, Credit 12000)
q = Person ( ID 321, Age 64, Credit 0)
e = Person ( ID 453, Age 30, Credit 3000)
r = Person ( ID 123, Age 65, Credit 2310)
s = Person ( ID 364, Age 32, Credit 32340)
t = Person ( ID 123, Age 65, Credit 1300)
org1 = [p,q,e]
org2 = [r,s,t]


hasPerson :: Gym->Int-> Bool
hasPerson gym' id' = not (null(filter hasperson' gym') )
    where 
         hasperson' person' = getID person' == id'

findID:: ID -> Organisation -> Int
findID id' org = total
    where
         IsInGym org' = hasPerson ( org' id' )
         validGym =  filter (IsInGym) org'
         total = sum ( map getCredit validGym)

1 个答案:

答案 0 :(得分:1)

首先,我建议使用记录代表您的人,除非您有特殊原因为每个字段指定新类型:

type ID = Int
type Age = Int
type Credit = Int
data Person = Person
    { personId :: ID
    , personAge :: Age
    , personCredit :: Credit
    } deriving (Eq, Show)

type Gym = [Person]
type Organization = [Gym]

接下来,您可以使用mapGym转换为[Int] personId,然后您可以使用内置elem来检查给出的ID出现在该列表中。

hasPerson :: Gym -> ID -> Bool
hasPerson gym pId = pId `elem` map personId gym

现在,对于findID函数,我建议将其重命名为organizationCredit,我会创建一个更简单的函数gymCredit来计算单个健身房:< / p>

gymCredit :: ID -> Gym -> Credit
gymCredit pId gym = sum $ map personCredit $ filter (\p -> personId p == pId) gym

organizationCredit :: ID -> Organization -> Credit
organizationCredit pId org = sum $ map (gymCredit pId) org

或者,您可以将您的功能声明为

gymCredit :: Person -> Gym -> Credit
gymCredit person gym = sum $ map personCredit $ filter (\p -> personId p == pId) gym
    where pId = personId person

organizationCredit :: Person -> Organization -> Credit
organizationCredit person org = sum $ map (gymCredit person) org

编辑:要坚持使用旧版本,您只需自己定义一些额外的功能,然后将它们放在您需要的代码中

newtype ID = ID Int deriving (Eq, Show)
newtype Age = Age Int deriving (Eq, Show)
newtype Credit = Credit Int deriving (Eq, Show)
newtype Person = Person (ID, Age, Credit) deriving (Eq, Show)
type Gym = [Person]
type Organisation = [Gym]

personId :: Person -> ID
personId (Person (i, a, c)) = i

personAge :: Person -> Age
personAge (Person (i, a, c)) = a

personCredit :: Person -> Credit
personCredit (Person (i, a, c)) = c

idVal :: ID -> Int
idVal (ID x) = x

ageVal :: Age -> Int
ageVal (Age x) = x

creditVal :: Credit -> Int
creditVal (Credit x) = x

gymCredit :: Person -> Gym -> Credit
gymCredit person gym = Credit $ sum $ map (creditVal . personCredit) $ filter (\p -> personId p == pId) gym
    where pId = personId person

organisationCredit :: Person -> Organisation -> Credit
organisationCredit person org = Credit $ sum $ map (creditVal . gymCredit person) org

值得注意的是,我已将Eq添加到每个新类型的派生类型类列表中。没有它,您将无法直接比较两个ID,您必须首先提取值。派生的另一个重要的类型类是Ord,它允许您使用<><=>=运算符,以及一大堆列出sort等函数。