Haskell中列表中的错误 - 交集

时间:2017-07-21 19:33:10

标签: haskell

这是一个很小的问题,我真的不知道我哪里错了。我需要创建一个函数来显示两个列表的交集(没有库和列表理解)。好吧,我做了这个,很简单,但是我犯了一个错误,导致函数返回的只是两个列表中的第一个元素相等。我知道这是一个愚蠢的错误。有人可以帮帮我吗?

这是功能:

inter :: [Int] -> [Int] -> [Int]
inter [] _ = []
inter _ [] = []
inter (x:xs) (y:ys) | (x == y) = x:[]
                    | otherwise = inter xs ys

错误的例子:(两个清单)[1,2,4] [1,3,4]

当正确的是:[1,4]

时,

仅返回[1]

2 个答案:

答案 0 :(得分:1)

您同时在两个列表上进行迭代并在第一个公共元素处停止。您需要检查列表成员资格并在找到第一个匹配元素后继续。我建议使用elem函数:

inter (x:xs) ys | elem x ys = ...
                | otherwise = inter xs ys

您需要在此处填写...,我故意将其留空,以便您了解自己需要做什么。

在你的功能中,它将会发生什么?

inter (1:2:4:[]) (1:3:4:[])

它将分配x = 1, y = 1, xs = 2:4:[], ys = 3:4:[],然后计算x == y,其评估为True,以便选择分支,返回x : []。或[1]。此时函数返回。它永远不会检查2 == 34 == 4

答案 1 :(得分:0)

假设:这是一个排序列表。

您的代码的工作原理如下:

inter :: [Int] -> [Int] -> [Int]
inter [] _ = []
inter _ [] = []
inter (x:xs) (y:ys) | (x == y) = x:[]         -- if x == y, we stop?
                    | otherwise = inter xs ys -- can we drop both elements?

前两行表示" 从其中一个列表[]开始,我们返回[] "。到目前为止一切都很好。

然后下一行与两名警卫合作。鉴于我们发现两个相等(x == y),我们只返回一个包含一个项[x]的列表。这是不正确的:有可能在两个尾部xsys中,两个集合中仍然存在项目。第二个警卫也是不正确的:如果x不等于y,那并不意味着我们可以抛弃这两个元素:x可能仍然在尾部{ {1}},或ys仍然在y某处。

然而,我们可以通过对两个列表进行排序来获得相当有效的解决方案。在这种情况下,我们可以简单地删除两者中最小的一个。由于xs已排序且ys,我们知道x < y中的所有元素也将大于ys

我建议的解决方案是:

x

此处inter :: [Int] -> [Int] -> [Int] inter [] _ = [] -- left list is empty, stop inter _ [] = [] -- right list is empty, stop inter xa@(x:xs) ya@(y:ys) | x == y = x : inter xs ys -- both head same, continue | x < y = inter xs ya -- left less, step left | otherwise = inter xa ys -- right less, step right是别名。 @表示我们引用了整个列表xa@(x:xs)以及头xa和尾x

通常一个目标是在Haskell中尽可能通用:现在我们必须为xs s,inter s等列表实现Int。这不是很典雅。我们可以将其概括为以下内容:

String