开发者

Filtering a list in Haskell

I am trying to start learning haskell, and a question came up. Say, I have a function

countFilter :: (a -> Bool) -> [a] -> ([a], Int)
countFilter a z = case z of []        -> ([], 0);
                            (x:xs)    -> (filter a z , length (filter a z))

开发者_开发问答It returns a list, all the items of which apply to a certain predicate and a length of that list, which is not relevant.

countFilter (<7) [1,2,4,7,11,8,2] will output ([1,2,4,2], 4).

How to create such an output: ([7,11,8], 4) using the same predicate (<7)?


If I understand your question correctly, you want to return all the elements that don't match the predicate (< 7) as the first element of the pair.

In that case you can simply use the not function to flip the resulting boolean.
I.e. create a new predicate (\x -> not (oldPred x)), or using function composition: (not . oldPred):

countFilter :: (a -> Bool) -> [a] -> ([a], Int)
countFilter f xs = (filter (not . f) xs, length (filter f xs))

Note that both filter and length can deal with empty lists, so you don't need to write a case yourself.


Alternatively, you can use the partition function to create the two lists, so that you don't filter the list twice:

import Data.List

countFilter :: (a -> Bool) -> [a] -> ([a], Int)
countFilter f xs = let (ys, zs) = partition (not . f) xs
                   in (ys, length zs)

It's probably possible to create an even more efficient version that doesn't use length, but I leave that as an exercise :-)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜