删除列表中第一次出现的给定元素



我需要编写一段代码,删除列表中第一次出现的给定元素。到目前为止,我只设法使代码删除了给定元素的每次出现。

她是我现在的代码:

rem2 :: Eq a => [a] -> a -> [a]
rem2 xs y = [x | x <- xs, x /= y]

如果我尝试:

rem2 "hello" 'l'

代码将返回" hero ",而我希望它返回" hero "。有人能帮帮我吗?

您可以在这里使用递归。如果到达列表的末尾,则返回空列表(1);如果给你一个非空列表(x:xs),并且列表的头部x与我们正在寻找的项目(2)匹配,我们返回列表的尾部xs;如果项目不匹配(3),我们产生x并递归到列表的尾部xs

这个函数看起来像:

rem1 :: Eq a => [a] -> a -> [a]
rem1 ls y = go ls
where go [] = …                  -- (1)
go (x:xs) | … = …          -- (2)
| otherwise = …  -- (3)

我把部分的实现留作练习。

delete的简化定义:

delete :: a -> [a] -> [a]
delete  _ []    = []
delete x (y:ys) = if x == y then ys else y : delete x ys

在实际库中使用更通用的函数deleteBy。这是源代码。

找到了一个可能的解决方案,但不是我想要的。解决方案如下:

import Data.List
rem1 :: Eq a => [a] -> a -> [a]
rem1 xs y = delete y xs

所以如果有人有一个不包括内置功能的解决方案,我很乐意听到你的声音。

下面是一个好奇心的解决方案,您可以使用列表推导式:

remfst :: Eq a => a -> [a] -> [a] 
remfst a xs 
| (j:_) <- 
[ i | (x,i) <- zip xs [0..], i <- [i | x == a]]
= [ x | (x,i) <- zip xs [0..], x <- [x | i /= j]]
remfst _ xs = xs

是"恶心"吗?在生产代码中,当然可以。在这里,这只是一些值得思考的事情。

现在我们有

> remfst 'l' "helalo"
"healo"

最新更新