【问题标题】:Haskell function that tests if a list has repeated (duplicate) elements测试列表是否具有重复(重复)元素的 Haskell 函数
【发布时间】:2014-10-06 13:56:07
【问题描述】:

我有一个练习要做,但是由于我是这门语言的新手,所以我找不到任何方法来做。

我有这个定义为“重复”的功能,在本段中给出。它接收一个 Int 列表并返回一个 Bool 值。它应该检查列表是否有任何重复的元素。如果是,则为真,否则为假。还有一个额外的:我必须通过递归来定义函数,所以它必须是递归函数。将不胜感激。

repeated :: [Int] -> Bool

EDIT1:到目前为止,我只成功使用了这么多代码

repeated :: [Int] -> Bool
repeated [] = False
repeated (h:t) = 

这只会让我返回空列表。其余的,我到现在都想不通……

EDIT2:忘记了单数列表...另外,可能的答案?

repeated :: [Int] -> Bool
repeated [] = False
repeated [_] = False
repeated (h:t) = if elem h t then True
                             else repeated t

差不多就是这样。我已经编译了 .hs 并且效果很好。谢谢大家的建议和提示! :)

【问题讨论】:

  • 这是排序的还是你可以先排序的?
  • 使用nub 可能更容易:repeated xs = xs == nub xs?
  • elem 功能可能会有所帮助。
  • 这取决于它是“重复”元素还是“重复”元素。我会将“重复”理解为“彼此相邻且相同的元素”,将“重复”理解为“列表中任何相同的元素”。重复与已排序的Ord a 的任意列表相同。
  • 作为旁注,我想指出这是一个极好的 SO 问题。你有一个特定的问题要解决,你迅速参与了讨论,将你的问题编辑为更合适和更清晰,并在你开始从提示中解决问题时添加代码。

标签: haskell


【解决方案1】:

您想查找列表是否有任何重复项。这意味着您必须跟上您已经访问过的元素列表,以便您可以检查它。所以首先,编写一个函数来检查单个元素是否存在于已访问值的列表中:

alreadyVisited :: Int -> [Int] -> Bool
alreadyVisited x [] = False
alreadyVisited x (v:visited) = ???

(注意:这在 Prelude 中称为elem,但您应该能够自己实现它,这是一种很好的做法)

然后,您将要编写循环遍历目标列表中所有元素的 main 函数,构建一组已访问的元素,直到找到重复项。一旦找到重复项,该函数可以退出而不检查列表的其余部分。

-- Using a helper hides the fact that the visited list is needed
repeated :: [Int] -> Bool
repeated xs = go xs []
--                   ^--  initial visited list is empty
    where
        -- same base case that you came up with,
        -- an empty list does not have duplicate elements
        go [] _ = False
        -- The recursive step, think about what you need this function to do
        go (x:xs) visited =
            if alreadyVisited x visited
                then ???        -- If it's already visited, do what?
                else ???        -- Otherwise?

这里我刚刚为您设置了结构,您必须自己填写详细信息。请记住,这不是一个有效的实现,特别是因为alreadyVisited 会随着visited 大小的增长而变得多么缓慢,但是如果您对速度感兴趣,那么您可以换掉访问过的Data.Set.Set 的列表,它的查找时间要好得多。

【讨论】:

  • 如果只是想知道列表是否包含重复项,您可以像这样使用 Data.List 中的 nub 函数:hasDup l = nub l == l(nub 删除所有重复项......所以只有在列表中没有重复项。)
【解决方案2】:

这是我的方法(使用集合和比较长度)

import qualified Data.Set as Set -- From the 'containers' library

hasDuplicates :: (Ord a) => [a] -> Bool
hasDuplicates list = length list /= length set
  where set = Set.fromList list

我正在使用containers Haskell Package

【讨论】:

    【解决方案3】:

    尝试使用nub

    import Data.List
    hasDuplicates :: (Ord a) => [a] -> Bool
    hasDuplicates xs = length (nub xs) /= length xs
    

    基本上,nub 将返回列表的唯一元素。

    【讨论】:

    猜你喜欢
    • 2019-05-03
    • 1970-01-01
    • 2011-10-06
    • 2020-07-06
    • 1970-01-01
    • 2014-02-17
    • 2021-12-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多