我有第一个列表和第二个列表,我想编写一个函数,该函数接受两个列表并返回一个列表,该列表仅包含第二个列表中未出现在第一个列表中的那些元素。而且我不想使用内置函数。例如:
> removeAll [1..3] [0..10]
[0,4,5,6,7,8,9,10]
> removeAll "aeiou" "supercalifragilisticexpialidocious"
"sprclfrglstcxpldcs"
removeAll _ [] = []
removeAll [] y = y
removeAll (x:xs) (y:ys)
| x==y = removeAll xs ys
| otherwise = y:removeAll xs ys
答案 0 :(得分:1)
这是一种简单的方法:
removeAll ignores = filter (\x -> notElem x ignores)
它利用:
如果您想使用“纯” Haskell编写它,而没有任何辅助功能……那么,听起来好像很丑陋,因为我们需要进行某种嵌套的for循环。这是一个折衷方案:
myFilter _ [] = []
myFilter pred (x:xs)
| pred x = x : myFilter pred xs
| otherwise = myFilter pred xs
myNotElem e [] = True
myNotElem e (x:xs)
| e == x = False
| otherwise = myNotElem e xs
removeAll ignores = myFilter (\x -> myNotElem x ignores)
答案 1 :(得分:0)
有一个非常简单的递归定义
removeAll :: Eq a => [a] -> [a] -> [a]
removeAll _ [] = []
removeAll toRemove (x:xs)
| x `belongs` toRemove = removeAll toRemove xs
| otherwise = x:removeAll toRemove xs
where belongs _ [] = False
belongs a (y:ys)
| a == y = True
| otherwise = belongs a ys
belongs
函数只是定义的elem
前奏。由于您不想使用内置函数,因此必须自行定义。
答案 2 :(得分:0)
当前代码的一个问题是您试图在一个函数中同时递归两个列表。您需要分而治之。如果允许elem
,则可以输入:
removeAll :: Eq a => [a] -> [a] -> [a]
removeAll _ [] = []
removeAll x (y:ys)
| myElem y x = removeAll x ys
| otherwise = y:removeAll x ys
如果您也不想使用内置的elem
,则可以类似地对其进行定义:
myElem :: Eq a => a -> [a] -> Bool
myElem _ [] = False
myElem x (y:ys)
| x == y = True
| otherwise = myElem x ys