Haskell:如何从Haskell中的列表中删除列表

时间:2018-11-22 05:30:45

标签: haskell

我有第一个列表和第二个列表,我想编写一个函数,该函数接受两个列表并返回一个列表,该列表仅包含第二个列表中未出现在第一个列表中的那些元素。而且我不想使用内置函数。例如:

> 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

3 个答案:

答案 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