比较两个列表的某些元素,Haskell

问题描述 投票:1回答:2

只是一个快速的免责声明我一直在学习Haskell大约一个月,一直在阅读,观看和搜索网络,但我不能理解这一点。

所以我的问题是,我想比较两个字符串说“p16201348”和“p16202068”并且基本上检查p之后的前两个数字是从2016年到16年。在我的下面的第一个例子中我只是使用相同的列表进行比较。当我将其输入到ghci时,它会按照您的预期评估为true。我的问题实际上是把它写成一个可调用的函数。

"p16201348" !! 1 == '1' && "p16201348" !! 1 == '1' && "p16201348" !! 2 == '6' && "p16201348" !! 2 == '6'

我写下这个函数的第一次尝试是在下面,因为我说p是无关紧要的,所以根据我的理解,我将列表拆分为x:xs butt忽略了头部,最终是_:xs和_:ys。当我试着调用它时,我得到了模棱两可的事件。

compare (_:xs) (_:ys) = xs !! 1 == '1' && ys !! 1 == '1' && xs !! 2 == '6' && ys !! 2 == '6'

我的最终功能(原型)是使用一个守卫方程,虽然我甚至不起诉如果可以拆分列表然后评估其中的某些元素

compare (_:xs)(_:ys)
    | xs !! 1  == '1' && ys !! 1 == '1' &&  xs !! 2  == '6' &&  ys !! 2 == '2' = "Same Year"
    | otherwise = "Different year"

在此先感谢您的帮助。

list haskell functional-programming pattern-matching
2个回答
4
投票

我们可以通过在模式匹配部分中执行相等性检查来使其更加优雅。此外,您的函数缺少例如数字不相等的情况,或者当我传递无效字符串时。

例如,对于"16"年,我们可以使用:

-- only works for the year 16
compare (_:'1':'6':_) (_:'1':'6':_) = "Same year"
compare _ _ = "Different year"

所以第一行检查列表的第二个和第三个元素是否分别是'1''6'。只有在那种情况下我们才会返回"Same year"。在所有其他情况下(第二行),我们返回"Different year"。因此,如果其中一个字符串少于三个字符,或者两个字符串至少有三个字符,但第二个和第三个字符分别不是'1'和/或'6',则最后一行将触发。

现在我们想要概括任何一年,我们可以使用变量:

compare (_:x1:x2:_) (_:y1:y2:_) = ...
compare _ _ = "Different year"

所以这里x1是第一个字符串的第二个字符,x2是同一个字符串的第三个字符。 y1是第二个字符串的第二个字符,y2是第二个字符串的第三个字符。

我们可能想确保这些都是数字,所以我们可以检查:

import Data.Char(isDigit)

compare (_:x1:x2:_) (_:y1:y2:_) | all isDigit [x1, x2, y1, y2] = ...
compare _ _ = "Different year"

所以现在我们有保证,如果警卫“开火”所有这些字符都是数字(在09范围内)。但当然我们仍然需要确定它们具有相同的价值。

我留下你必须填写的椭圆(...)作为练习,它基本上是问题中代码的概括。


0
投票

再次感谢您的所有建议,非常感谢。所以我发现为什么我的代码不起作用,这是因为我使用Haskell内置函数“compare”作为我的函数名。所以,一旦我将它们命名,它们就会结账。

只是为了澄清我的问题是,比较一个身份证号码的第二和第三个元素,例如P16201348。这些元素表示两个数字是否来自同一年,16,17等。

我带的代码就是这个,

pnum :: Eq a => [a] - > [a] - > Bool

pnum(:xs)(:ys)= xs !! 1 == ys !! 1 && xs !! 2 == ys !! 2

所以,我在每个列表的头部使用下划线,因为这个元素并不重要。然后我比较我需要的元素并检查它们是否相等。

我的意思是这可能不是最好和最有效的方法,所以如果你不这样做,请告诉我。

谢谢

© www.soinside.com 2019 - 2024. All rights reserved.