Haskell 查找列表中的第一个重复元素
我对哈斯克尔很陌生。我试图用Haskell编写代码,从列表中找到第一个重复的元素,如果没有重复的元素,则消息不会重复。我知道我可以通过Haskell 查找列表中的第一个重复元素,haskell,functional-programming,Haskell,Functional Programming,我对哈斯克尔很陌生。我试图用Haskell编写代码,从列表中找到第一个重复的元素,如果没有重复的元素,则消息不会重复。我知道我可以通过nub函数来完成,但我尝试在没有它的情况下完成它。这是一种方法: import qualified Data.Set as Set dup :: Ord a => [a] -> Maybe a dup xs = dup' xs Set.empty where dup' [] _ = Nothing dup' (x:xs) s =
nub
函数来完成,但我尝试在没有它的情况下完成它。这是一种方法:
import qualified Data.Set as Set
dup :: Ord a => [a] -> Maybe a
dup xs = dup' xs Set.empty
where dup' [] _ = Nothing
dup' (x:xs) s = if Set.member x s
then Just x
else dup' xs (Set.insert x s)
dupString :: (Ord a, Show a) => [a] -> [Char]
dupString x = case dup x of
Just x -> "First duplicate: " ++ (show x)
Nothing -> "No duplicates"
main :: IO ()
main = do
putStrLn $ dupString [1,2,3,4,5]
putStrLn $ dupString [1,2,1,2,3]
putStrLn $ dupString "HELLO WORLD"
以下是它的工作原理:
*Main> main
No duplicates
First duplicate: 1
First duplicate: 'L'
这是一种方法:
import qualified Data.Set as Set
dup :: Ord a => [a] -> Maybe a
dup xs = dup' xs Set.empty
where dup' [] _ = Nothing
dup' (x:xs) s = if Set.member x s
then Just x
else dup' xs (Set.insert x s)
dupString :: (Ord a, Show a) => [a] -> [Char]
dupString x = case dup x of
Just x -> "First duplicate: " ++ (show x)
Nothing -> "No duplicates"
main :: IO ()
main = do
putStrLn $ dupString [1,2,3,4,5]
putStrLn $ dupString [1,2,1,2,3]
putStrLn $ dupString "HELLO WORLD"
以下是它的工作原理:
*Main> main
No duplicates
First duplicate: 1
First duplicate: 'L'
这不是您的最终答案,因为当一个元素被多次复制而不是立即返回时,它会做不必要的工作,但它说明了您可以如何系统地运行所有的可能性(例如,“列表中的这个元素在列表的下一步是否有重复项?”)
dupwonub::Eq a=>[a]->[a]
dupwonub[]=[]
dupwonub(x:xs)=情况[y | y[y]
[]->dupwonub xs
这不是您的最终答案,因为当一个元素被复制多次而不是立即返回时,它会做不必要的工作,但它说明了您可以如何系统地运行所有的可能性(例如,“列表中的这个元素在列表的下一步是否有重复项?”)
dupwonub::Eq a=>[a]->[a]
dupwonub[]=[]
dupwonub(x:xs)=情况[y | y[y]
[]->dupwonub xs
如果您仍在研究Haskell,我想您可能需要一个更快但更复杂的解决方案。该解决方案以O(n)(我认为)形式运行,但对列表的类型有一个稍微严格的限制,即必须是Ix
类型
accumArray
是一个非常有用的功能,如果您还没有使用过,建议您研究一下
import Data.Array
data Occurances = None | First | Duplicated
deriving Eq
update :: Occurances -> a -> Occurances
update None _ = First
update First _ = Duplicated
update Duplicated _ = Duplicated
firstDup :: (Ix a) => [a] -> a
firstDup xs = fst . first ((== Duplicated).snd) $ (map g xs)
where dupChecker = accumArray update None (minimum xs,maximum xs) (zip xs (repeat ()))
g x = (x, dupChecker ! x)
first :: (a -> Bool) -> [a] -> a
first _ [] = error "No duplicates master"
first f (x:xs) = if f x
then x
else first f xs
注意,一个大小为
(最小xs,最大xs)
的数组可能会大大增加您的空间需求。如果您仍在研究Haskell,我想您可能会想要一个更快但更复杂的解决方案。这在O(n)(我想)中运行,但对列表的类型有稍微严格的限制,即必须是Ix
类型
accumArray
是一个非常有用的功能,如果您还没有使用过,建议您研究一下
import Data.Array
data Occurances = None | First | Duplicated
deriving Eq
update :: Occurances -> a -> Occurances
update None _ = First
update First _ = Duplicated
update Duplicated _ = Duplicated
firstDup :: (Ix a) => [a] -> a
firstDup xs = fst . first ((== Duplicated).snd) $ (map g xs)
where dupChecker = accumArray update None (minimum xs,maximum xs) (zip xs (repeat ()))
g x = (x, dupChecker ! x)
first :: (a -> Bool) -> [a] -> a
first _ [] = error "No duplicates master"
first f (x:xs) = if f x
then x
else first f xs
小心tho,一个大小
的数组(最小x,最大x)
可能会大大增加您的空间需求。我建议您仔细阅读haskell文档,并努力编写一些有用的东西。如果您陷入困境,不明白哪里出了问题,请发布一个包含问题的代码示例,以表明您已对该问题进行了思考。请在此处查看教程列表这是学习该语言的一个很好的参考资料。强烈建议您从Haskell开始学习。不要让愚蠢的绘图蒙蔽您;这是对该语言的一个很好的介绍。此外,您在堆栈溢出问题上提出的下一个问题的标题应该没有“Haskell编程”那么笼统。我建议你仔细阅读haskell文档,努力写一些有用的东西。如果你陷入困境,不明白哪里出了问题,请在问题中发布一个代码示例,表明你对这个问题做了一些思考。在这里查看教程列表,这将是学习该语言的一个很好的参考资源。我强烈建议您从Haskell开始。不要让愚蠢的绘图愚弄您;这是对该语言的极好介绍。此外,您在堆栈溢出问题上提出的下一个问题的标题应该没有“Haskell编程”那么笼统.如果你必须为OP做家庭作业,至少要礼貌地解释你提出解决方案的过程,或者在简单的代码之外启发问题(这对他来说可能是一门外语). -1@luqui如果OP有任何具体问题,我很乐意回答。如果没有反馈,我很难知道从哪里开始解释。而且,当我回答这个问题时,它没有家庭作业标签。@dbyrne,是的,我知道。我是在看到其他多个用户问同一个问题后添加的,显然我不希望你没有提前做某事是否是家庭作业。我通常假设是这样做的,特别是如果有人要求我为他们实施某件事。家庭作业或不做作业,如果你把他们放在比复印和粘贴更费劲的地方,我会学到更多,我认为这是一个教育网站(我意识到这不是万能的)。我想让你给我一个指引,而不是一个包装好的产品。特别是一个评论说:“你尝试了什么?”鼓励海报在给他们答案之前付出更多的努力是一个很好的方法来培养这一点。正如我所说的,我不认为这个问题值得回答。.这个答案从那时起就被删除了。这是你的主观意见,认为它不值得回答。这很好,但我的意见是这样的。OP的问题很清楚,很容易给出正确的答案。我自己也是haskell初学者,我认为尝试一下是一个很好的练习。一旦我想出了解决方案如果你必须为OP做家庭作业,至少要礼貌地解释你提出解决方案的过程,或者在简单的代码之外启发问题(这对他来说可能是一门外语). -1@luqui如果OP有任何具体问题,我很乐意回答。如果没有反馈,我很难知道从哪里开始解释。而且,当我回答这个问题时,它没有家庭作业标签。@dbyrne,是的,我知道。我是在看到其他多个用户问同一个问题后添加的,显然我不希望你没有o事先判断某件事是否是家庭作业。我通常假定它是家庭作业,尤其是当有人要求我实施某件事时