我被要求创建一个函数来计算[Int]上的负数,零数和正数。然后应将结果写在元组(nrOfNeg,nrOfZeros,nrOfPos)上。
nzp [0,-1,1,2,0,3] =(1,2,3)
但是,列表必须只被覆盖一次(这意味着元组应该更新它在[Int]上评估的每个元素。)
类似的东西:
nzp [***0***,-1,1,2,0,3] = (0,1,0)
nzp [0,***-1***,1,2,0,3] = (1,1,0)
nzp [0,-1,***1***,2,0,3] = (1,1,1)
...
这是我到目前为止所做的,但它“使用”列表的3倍来计算。
nzp :: [Int] -> (Int,Int,Int)
nzp l = (neg,zeros,pos)
where neg = length (filter (<0) l)
zeros = length (filter (==0) l)
pos = length (filter (>0) l)
在评估[Int]的元素时,有没有办法增加元组的特定位置?
答案 0 :(得分:2)
count :: (Num a, Ord a, Foldable f) => f a -> (Int, Int, Int)
count = foldl' go (0, 0, 0) where
go (!neg, !zer, !pos) x =
case compare x 0 of
LT -> (neg + 1, zer, pos)
EQ -> (neg, zer + 1, pos)
GT -> (neg, zer, pos + 1)
使用foldl
包
import qualified Control.Foldl as Fl
import Control.Lens.Fold
countF :: (a -> Bool) -> Fl.Fold a Int
countF p = Fl.handles (filtered p) Fl.length
count = Fl.fold ((,,) <$> countF (<0) <*> countF (==0) <*> countF (>0))
答案 1 :(得分:0)
你不能真正更新一个元组,因为值在Haskell中是不可变的。但是,您可以使用更新的值从上一个创建一个新的。提示,使用fold
或简单的递归。
答案 2 :(得分:0)
这是foldl
的一个很好的用例:
nzp :: [Int] -> (Int, Int, Int)
nzp = foldl accountForNumber (0, 0, 0)
where accountForNumber (lt, eq, gt) x | x < 0 = (lt + 1, eq, gt)
accountForNumber (lt, eq, gt) x | x > 0 = (lt, eq, gt + 1)
accountForNumber (lt, eq, gt) _ | otherwise = (lt, eq + 1, gt)