我是Haskell的新手,一直试图获取基础知识。从列表中删除x的第一个实例
假设我有以下列表Y:
3:3:2:1:9:7:3:[]
我试图找到一种方法来删除的3名单y中的第一次出现。这可能使用简单的列表理解吗?
我想什么(这个方法删除所有实例从列表):
deleteFirst _ [] = []
deleteFirst a (b:bc) | a == b = deleteFirst a bc
| otherwise = b : deleteFirst a bc
我是Haskell的新手,一直试图获取基础知识。从列表中删除x的第一个实例
假设我有以下列表Y:
3:3:2:1:9:7:3:[]
我试图找到一种方法来删除的3名单y中的第一次出现。这可能使用简单的列表理解吗?
我想什么(这个方法删除所有实例从列表):
deleteFirst _ [] = []
deleteFirst a (b:bc) | a == b = deleteFirst a bc
| otherwise = b : deleteFirst a bc
作为其他已经提到的列表理解不是一个适当的解决这个任务(难以终止一步执行)。
你几乎写正确的解决方案,只需在匹配的价值平等的,你必须通过不匹配的元素返回列表的其余部分终止计算的情况下:
deleteFirst _ [] = []
deleteFirst a (b:bc) | a == b = bc
| otherwise = b : deleteFirst a bc
> print $ deleteFirst 3 (3:3:2:1:9:7:3:[])
> [3,2,1,9,7,3]
呃,我看到sepp2k和Joachim Breitner已经提到了修复。 –
不是前奏有内置的吗? – theonlygusti
我不相信这是可能的(在任何习惯的方法至少不会)与列表理解来做到这一点。你的deleteFirst
的作品差不多。您需要修改的是在第一次匹配后停止删除,即在第一个子句中将deleteFirst a bc
替换为bc
。
不,使用列表理解是不可能的。在列表理解中,您仅根据该元素来决定保留哪个元素。在你的例子中,你想对待你遇到的前3个不同于其他3个(因为你只想删除第一个),所以决定不依赖于单独的元素。所以列表理解不起作用。
您使用递归函数的尝试已经非常接近,除非如您所说,它会删除所有实例。为什么它会删除所有实例?因为在删除第一个之后,您会在列表的其余部分再次调用deleteFirst
,这将删除下一个实例等等。要解决这个问题,请在删除第一个实例后再次调用deleteFirst
。所以在这种情况下只需使用bc
而不是deleteFirst a bc
。
sepp2k的有关言论列表理解是重要的事情要了解;像map
,filter
,foldr
等对待所有列表项统一列表操作,并了解关于他们最重要的事情是什么样的信息可以在每一个步骤,以及如何每一步的结果与其他步骤相结合。
但我想强调的一点是,我认为你应该真的试图解决这些问题的库函数方面。从this older answer of mine解决方案适应您的问题:
deleteFirst x xs = beforeX ++ afterX
-- Split the list into two pieces:
-- * prefix = all items before first x
-- * suffix = all items after first x
where (beforeX, xAndLater) = break (/=x) xs
afterX = case xAndLater of
[] -> []
(_:xs) -> xs
诀窍是,break
已经内置了它的“达人第一击”的行为。作为进一步的练习,你可以尝试编写你自己的版本break
;学习如何编写这些小的,通用的和可重用的函数总是有益的。
'3:3:2:1:9:7:3'不是一个列表。你可能意味着'[3,3,2,1,9,7,3]'其是用于句法舒加'3:3:2:1:9:7:3:[]' –
感谢指出了这一点。对不起,这是一个错字,请参阅编辑。 – AnchovyLegend
您试图重新实现'Data.List.delete',它被定义为'deleteBy(==)'。如果你被困住了,你总是可以[看看Hackage上的源代码](http://hackage.haskell.org/packages/archive/base/latest/doc/html/src/Data-List.html #deleteBy)。 – David