如何基于谓词实现列表拆分器
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何基于谓词实现列表拆分器相关的知识,希望对你有一定的参考价值。
我试图基于给定谓词实现列表拆分器。功能类似于递归break.I在列表中输入,并且只要给定元素的谓词为真,我就将元素附加到小列表中当谓词为假时,我将形成的列表附加到一个更大的列表中,并且我继续从那里忽略对应于错误谓词的元素。
P.S:我试图不使用任何Data.List函数只能自我实现。(我正处于学习阶段)。例:
输入
谓词:(x->x<3)
列表:[1,2,3,2,3,1,1,1,3]
输出:
[[1,2],[2],[1,1,1]]
到目前为止,我已尝试使用以下方法:我使用一个列表给出一个列表,它在2的元组中将其分解。第一个元素是列表,直到假谓词。第二个是其余的。我将这个元组提供给一个一次又一次地执行此操作的功能。
splt::(a->Bool)->[a]->[[a]]
splt p []=[]
splt p (x:xs)=go p [] (x:xs) where
go p rez []=rez
go p rez ls=rez:process . brk $ ls [] where
process (x,[])=rez:x
process ([],x)=go p rez x
brk::(a->Bool)->[a]-> ([a],[a])
brk p []= ([],[])
brk p (x:xs)=go p ([],x:xs) where
go p (accu,[])= (accu,[])
go p (accu,x:xs)|not (p x) =(accu,xs)
|otherwise = go p (x:accu,xs)
我收到以下错误:cannot produce infinite type.
我也尝试过一个更简单的解决方案:
format::(a->Bool)->[a]->[[a]]
format p []=[]
format p ls=go p [] [] ls where
go p small big []=small:big
go p small big (x:xs)=case p x of
True ->go p x:small big xs
False ->go p [] small:big xs
但它不起作用,我也必须在两种情况下扭转结果。我得到的错误是:
* Couldn't match type `a' with `[a0]'
`a' is a rigid type variable bound by
the type signature for:
wrds :: forall a. (a -> Bool) -> [a] -> [[a]]
at Ex84.hs:12:5-31
Expected type: [a0] -> Bool
Actual type: a -> Bool
* In the first argument of `go', namely `p'
In the expression: go p [] []
ls
答案
第二个问题只是一个包围问题,可以通过正确地将参数加括号来解决,如下所示:
case p x of
True ->go p (x:small) big xs
False ->go p [] (small:big) xs
如果不这样做,列表将被视为功能。在这种情况下,您还必须在结果列表中反向映射。
您也可以尝试使用span函数:
splt :: (a -> Bool) -> [a] -> [[a]]
splt _ [] = []
splt p xs = let (xs', xs'') = span p xs
remaining = dropWhile (not . p) xs''
in case xs' of
[] -> splt p remaining
xs' -> xs' : splt p xs''
另一答案
这是实现您需要的方式。
我所做的是使用函数span
,它将列表分成两部分,返回一个元组。第一个元素是满足p
的初始元素列表。元组的第二个元素是列表的其余部分。
我递归地使用了这个,同时丢弃了不满足p
的元素。
splt :: (a -> Bool) -> [a] -> [[a]]
splt p [] = []
splt p ls = let (a,rs) = span p ls
(b,rs') = span (not . p) rs
in if null a then splt p rs' else a : splt p rs'
您也可以尝试自己定义span
以上是关于如何基于谓词实现列表拆分器的主要内容,如果未能解决你的问题,请参考以下文章