过滤Haskell中的列表

bog*_*jov 2 haskell functional-programming list filter

我正在尝试开始学习haskell,并提出了一个问题.说,我有一个功能

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

它返回一个列表,其中所有项都适用于某个谓词和该列表的长度,这是不相关的.

countFilter (<7) [1,2,4,7,11,8,2]将输出([1,2,4,2], 4).

如何创建这样的输出:([7,11,8], 4)使用相同的谓词(<7)?

Tom*_*rst 5

如果我正确理解了您的问题,您希望返回与谓词匹配的所有元素(< 7)作为该对的第一个元素.

在这种情况下,您可以简单地使用该not函数来翻转结果布尔值.
即创建一个新的谓词(\x -> not (oldPred x)),或使用函数组合(not . oldPred)::

countFilter :: (a -> Bool) -> [a] -> ([a], Int)
countFilter f xs = (filter (not . f) xs, length (filter f xs))
Run Code Online (Sandbox Code Playgroud)

注意,这两个filterlength可以处理空列表,所以你不需要写case自己.


或者,您可以使用分区功能创建两个列表,这样您就不会过滤两次列表:

import Data.List

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

可能有可能创建一个更有效的版本而不使用length,但我把它留作练习:-)