这是一个很小的问题,我真的不知道我哪里错了。我需要创建一个函数来显示两个列表的交集(没有库和列表理解)。好吧,我做了这个,很简单,但是我犯了一个错误,导致函数返回的只是两个列表中的第一个元素相等。我知道这是一个愚蠢的错误。有人可以帮帮我吗?
这是功能:
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]
答案 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 == 3
或4 == 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]
的列表。这是不正确的:有可能在两个尾部xs
和ys
中,两个集合中仍然存在项目。第二个警卫也是不正确的:如果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