[英]Filtering a list in Haskell
I am trying to start learning haskell, and a question came up. 我试图开始学习haskell,然后提出了一个问题。 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)
. countFilter (<7) [1,2,4,7,11,8,2]
将输出([1,2,4,2], 4)
。
How to create such an output: ([7,11,8], 4)
using the same predicate (<7)? 如何创建这样的输出: ([7,11,8], 4)
使用相同的谓词(<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. 如果我正确理解了您的问题,则希望返回与谓词(< 7)
不匹配的所有元素作为该对中的第一个元素。
In that case you can simply use the not
function to flip the resulting boolean. 在这种情况下,您可以简单地使用not
函数来翻转结果布尔值。
Ie create a new predicate (\\x -> not (oldPred x))
, or using function composition: (not . oldPred)
: 即创建一个新的谓词(\\x -> not (oldPred x))
或使用函数组合: (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. 请注意, filter
和length
都可以处理空列表,因此您无需自己编写case
。
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 :-) 可能有可能创建一个不使用length
更有效的版本,但我将其留为练习:-)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.