我想计算列表中正整数/元素的数量。这将返回具有正值的元素,我该如何计算元素?想要构造类似count(array(...))的东西。
我希望看到带有 i ++ 和 foldl 的版本。那会很有帮助。
countPositivesRec :: [Int] -> [Int]
countPositivesRec [] = []
countPositivesRec (x:xs) | x >= 0 = x : tl
| otherwise = tl
where tl = countPositivesRec xs
答案 0 :(得分:1)
这里有个提示:遵循与以前相同的递归方案,但是在每个步骤都返回一个int。
countPositivesRec :: [Int] -> Int
---
countPositivesRec [] = 0 -- no positives in the empty list
countPositivesRec (x:xs) | x >= 0 = ??
| otherwise = ??
where tl = countPositivesRec xs
您可以解决这个问题,如果需要,可以使用foldr
进行重写。
如果您真的想使用foldl
,建议您先定义一个函数f
,这样
f (f (f 0 x0) x1) x2
求出x0,x1,x2
中的正数。然后,您可以使用foldl f 0 inputList
答案 1 :(得分:1)
您编写的函数为filter (>=0)
。正如Paul所指出的,剩下的唯一步骤就是计数,length
做到了。我们可以逐步转换功能:
countPositivesRec :: [Int] -> [Int]
countPositivesRec [] = []
countPositivesRec (x:xs) | x >= 0 = x : tl
| otherwise = tl
where tl = countPositivesRec xs
请注意,xs
仅以转换后的形式tl
使用。这就是让它正确折叠的原因。
onlypos1 = foldr maybekeep []
where maybekeep x tl | x >= 0 = x : tl
| otherwise = tl
此操作称为filter
,仅保留部分内容:
onlypos2 = filter dowekeep
where dowekeep x = x >= 0
onlypos3 = filter (\x -> x >= 0)
onlypos4 = filter (>= 0)
但这当然只是许多可能方法中的一种。例如,严格性分析可以得出这样的结论:length
比foldl' (\a _ -> succ a) 0
更好地实现为foldr (\_ a -> succ a) 0
。确实,这是前奏曲中的基本形式:
length = foldl' (\c _ -> c+1) 0
我们看到length
的组合函数忽略了一个参数的值,只要求它存在。这可以自然地与我们只需要某些元素计数的条件合并:
lengthFilter1 = length . filter
lengthFilter2 pred = foldl' predCount 0
where predCount c x = if pred x then c+1 else c
countNonNegative = lengthFilter2 nonNegative
where nonNegative x = x >= 0
顺便说一句,0不是正数。这是非负的。
最后,Haskell的惰性列表意味着我们可以使用它们来融合遍历。 length . filter (>=0)
只读取一次输入列表,因为它处理filter
的结果的唯一原因是length
消耗了它们。与例如Python或PHP。这种形式可能是最易读的形式之一,但也存在其他形式,例如:
countNonNegatives xs = sum [1 | x <- xs, x >= 0]
答案 2 :(得分:1)
你有
filtering p cons x r = if | p x -> cons x r | otherwise -> r
countPositives = length
. filter (> 0)
= foldr (\x r -> r + 1) 0 -- r++
. foldr (filtering (> 0) (:) ) []
= foldr (filtering (> 0) (\x r -> r + 1)) 0
(由于通过组合其变矩器来折叠 fuse ,a-la “ fold用reducer操作替换了缺点,因此,如果要替换,为什么要首先创建缺点无论如何” )和
filtering (> 0) (\x r -> r + 1) x r
= if | (> 0) x -> (\x r -> r + 1) x r | otherwise -> r
= if | x > 0 -> r + 1 | otherwise -> r
,因此是您想要的具有 fold 和 increment 的版本,
countPositives = foldr (\x r -> if | x > 0 -> r + 1 | otherwise -> r) 0 -- r++
您可以从这里拿走它。