帮助我理解为什么函数 removeDuplicates
只有一个参数,但它下面的函数 rdHelper
有两个?它有效,并且在列表中尝试没有错误。
removeDuplicates :: Eq a => [a] -> [a]
removeDuplicates = rdHelper []
where rdHelper seen [] = seen
rdHelper seen (x:xs)
| x `elem` seen = rdHelper seen xs
| otherwise = rdHelper (seen ++ [x]) xs
也许它与状态变量有关?但我不确定它是什么
最佳答案
为了删除重复项,您需要以某种方式存储您已经看到的值。这就是变量被称为seen
的原因。最初在递归中,您没有看到任何元素,因此 seen
为空。
但是,每次您发出 一个值时,都会将其添加到累加器seen
。假设您调用 removeDuplicates [1,2,3,1,4,2]
。然后它将被评估为:
removeDuplicates [1,2,3,1,4,2]
rdHelper [] [1,2,3,1,4,2]
(1 : rdHelper [1] [2,3,1,4,2])
所以现在 rdHelper
将被调用,我们知道 1
已经发出,所以我们应该将其过滤掉。接下来我们执行:
removeDuplicates [1,2,3,1,4,2]
rdHelper [] [1,2,3,1,4,2]
(1 : rdHelper [1] [2,3,1,4,2])
(1 : 2 : rdHelper [1,2] [3,1,4,2])
(1 : 2 : 3 : rdHelper [1,2,3] [1,4,2])
所以现在我们遇到这样一种情况,其中 1
位于第二个列表的头部,但因为它也是 seen
的 elem
,我们将忽略该元素。
您的代码中存在错误,因为 rdHelper
从不发出任何内容。还要注意,您可以通过添加到头部来提高性能(添加到头部不会改变程序的语义,但会使其运行得更快):
removeDuplicates :: Eq a => [a] -> [a]
removeDuplicates = rdHelper []
where rdHelper _ [] = []
rdHelper seen (x:xs)
| x `elem` seen = rdHelper seen xs
| otherwise = <b>x : </b>rdHelper <b>(x:seen)</b> xs
-- ^emit element ^add to head
https://stackoverflow.com/questions/42489878/