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

时间:2018-02-27 13:12:29

标签: list haskell functional-programming pattern-matching

快速免责声明我一直在学习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'

我的最终功能(protptype)正在使用一个保护等式,尽管如果可以拆分列表然后评估其中的某些元素,我甚至不会起诉

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

提前感谢您的帮助。

2 个答案:

答案 0 :(得分: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范围内)。但当然我们仍然需要确定它们具有相同的价值。

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

答案 1 :(得分:0)

再次感谢所有建议,非常感谢。 所以我发现为什么我的代码没有工作,这是因为我使用的是Haskell内置函数"比较"作为我的功能名称。所以,一旦我将它们命名,他们就会检查出来。

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

我带的代码就是这个,

pnum :: Eq a => [a] - > [a] - >布尔

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

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

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

由于