我有一个练习,但由于我是这门语言的新手,我找不到任何方法可以做到。
我有这个功能"重复"根据本段给出的定义如此。它接收一个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,它运作得很好。谢谢大家的建议和提示! :)
答案 0 :(得分:5)
您想要查找列表是否有任何重复项。这意味着您必须跟上已经访问过的元素列表,以便进行检查。首先,编写一个函数来检查已访问过的值列表中是否存在单个元素:
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
的访问列表换出,查找时间要好得多。
答案 1 :(得分:4)
这是我的方法(使用集合和比较长度)
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
答案 2 :(得分:1)
尝试使用nub。
import Data.List
hasDuplicates :: (Ord a) => [a] -> Bool
hasDuplicates xs = length (nub xs) /= length xs
基本上,nub
将返回列表的唯一元素。