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 :-)
精彩评论