如何基于谓词实现列表拆分器

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

以上是关于如何基于谓词实现列表拆分器的主要内容,如果未能解决你的问题,请参考以下文章

在每个谓词 scala 处将字符串列表拆分为多个列表

组合多个谓词不起作用

将序言中的列表拆分为原子和整数

Prolog - 将单词分成单独的字母

如何从 Java 中的自定义谓词列表中创建一个谓词?

Python代码阅读(第38篇):根据谓词函数和属性字符串构造判断函数