从Haskell中的列表中删除重复的元素

从Haskell中的列表中删除重复的元素,haskell,Haskell,我是哈斯克尔的初学者。我只是想知道如何实现从数组中删除repeat元素的函数。例如,[1,1,1,3,4,2,2,3],结果应该是[1,3,4,2]。我不想使用像element这样的exist函数,而是通过递归来实现它。我的想法是比较x:xs,如果x是重复元素,那么执行递归,否则重新运行该函数。这是正确的吗?如何通过代码实现这一点 您可以看看Haskell提供的nub函数 这是什么代码: nub :: (Eq a) => [a] -> [a]

我是哈斯克尔的初学者。我只是想知道如何实现从数组中删除repeat元素的函数。例如,[1,1,1,3,4,2,2,3],结果应该是[1,3,4,2]。我不想使用像element这样的exist函数,而是通过递归来实现它。我的想法是比较x:xs,如果x是重复元素,那么执行递归,否则重新运行该函数。这是正确的吗?如何通过代码实现这一点

您可以看看Haskell提供的
nub
函数

这是什么代码:

nub                     :: (Eq a) => [a] -> [a]
nub                      = nubBy (==)

nubBy                   :: (a -> a -> Bool) -> [a] -> [a]
nubBy eq []              = []
nubBy eq (x:xs)          = x : nubBy eq (filter (y -> not (eq x y)) xs)
事实上,我发现一个网页向您展示了一个比Haskell提供的更高效的实现:

如果您不能假定元素之间有任何顺序(即您不知道它是否是
Ord
的实例),那么您必须使用
nub
,就像一张海报已经提到的那样。不幸的是,这是O(n^2)

如果您的元素实现了
Ord
,那么您可以按O(nlog(n))对列表进行排序,然后递归地删除相邻的元素(这只会将O(n)添加到整个运行时)。大概是这样的:

remove_dups :: (Ord a, Eq a) => [a] -> [a]
remove_dups xs = remove $ sort xs
  where
    remove []  = []
    remove [x] = [x]
    remove (x1:x2:xs)
      | x1 == x2  = remove (x1:xs)
      | otherwise = x1 : remove (x2:xs)
很有趣的问题。我们经常需要做这种事情

编辑


我没有注意到你给出的结果不是按非降序排列的。上面的代码将生成
[1,2,3,4]
,而这可能不是您想要的。

您的思路是正确的:您正在考虑列表的头部(
x
,在您的示例中)和尾部(
xs
)。正如您所建议的,您需要做两件事:

  • 编写一个函数,在
    xs
    中删除任何重复的
    x
  • 处理列表中的其他部分。。。既然
    xs
    中的
    x
    的任何重复项都消失了,您将如何处理?在纸上手动尝试,观察你的大脑在做什么
  • 首先尝试解决第一个任务,并确保您编写的函数在某些测试用例上工作(在GHCi或其他方面进行尝试,直到您满意它工作为止)


    对于第二项任务,当你手动解决这个问题时,尝试并观察你的大脑是如何运作的,这同样非常有帮助。

    这个问题有很多解决方案,想要的解决方案可能取决于你的课程到目前为止所涵盖的内容

    我将观察到,“exists”函数通常具有对数运行时间,这取决于所使用的数据结构,构建最好的数据结构需要最坏的“n logn”时间

    如果这听起来像胡言乱语,不要担心。您将在算法或复杂性理论课程中学习运行时间。我只是说一个精心设计的函数比你想象的要快得多


    另一方面,有一种称为散列函数的函数可以让您为更大的数组进行更细粒度的时空权衡,但这超出了您当前课程的范围

    我也在学习Haskell,我写了这段代码。我想它解决了你的问题。我用我能想到的最简单的方法做了

    takeRep :: Eq a => [a] -> [a]  
    takeRep [] = []
    takeRep (x:xs)
        | checkIt x xs = takeRep xs
        | otherwise = x:takeRep xs
    
    checkIt :: Eq a => a -> [a] -> Bool
    checkit _ [] = False
    checkIt n (x:xs)
        | n == x = True
        | otherwise = checkIt n xs
    

    挑剔:
    [1,1,1,3,4,2,2,3]
    不是数组,而是链表。其实,这是工作的一部分,我想不出来。其他部分我已经完成了。嗯,是7秒,海报上没有写是给他/她的家庭作业。“我的回答是相信它不是。”奥古斯都我在它被贴上作业标签之前回答。编辑我找到了关于家庭作业政策的部分()虽然它不是官方的,但我会记住它。另一方面,请注意,这是单个google搜索的结果,并且它只是haskell库提供的实现。换句话说,我没有向他展示任何他不容易找到的东西。如果表现很重要,那么也要考虑。