在Haskell中删除或添加项目到列表

时间:2019-09-07 20:09:32

标签: list haskell

我必须设计一个功能removeOrAdd :: a -> [a] -> [a]。我直接的解决方案:

removeOrAdd :: Eq a => a -> [a] -> [a]
removeOrAdd x xs | x `elem` xs = [x' | x' <- xs, x' /= x]
                 | otherwise   = x : xs

但是,我感觉自己正在做别人已经做过的事情。 Haskell中是否已有任何功能?


UPD::让我们将列表视为Set,我们希望列表中没有多个x,否则我们将其全部删除。

1 个答案:

答案 0 :(得分:3)

  

Haskell中是否已有任何功能?

据我所知,在Hoogle上进行搜索并没有立即列出该功能。我认为这很奇怪,因为通常一个人旨在添加或删除,但并非同时取决于条件。

我们可以通过使它更懒(可以使它在从未发生x的无限列表上工作)来改进上述功能,并且在不对列表进行两次迭代的意义上说,效率更高。 。我们可以为此使用显式递归:

removeOrAdd :: Eq a => a -> [a] -> [a]
removeOrAdd x = go
    where go [] = [x]
          go (y:ys) | x == y = ys
                    | otherwise = y : go ys

因此,我们在此处遍历列表,一直进行迭代,直到找到等于y的元素x。在这种情况下,我们返回ys,我们已经完成了,因为我们删除了该项目。如果不是,则通过递归到达列表的末尾,我们知道x不属于列表,因此我们返回[x]以添加该元素。因此,我们在此处将元素添加到列表的 end

如果列表已排序,我们可以将其插入正确的位置:

removeOrAdd :: Ord a => a -> [a] -> [a]
removeOrAdd x = go
    where go [] = [x]
          go (y:ys) | x == y = ys
                    | y > x = x : y : ys
                    | otherwise = y : go ys

因此,我们在这里将物品保持正确的顺序。