Haskell - 使用foldr的MinMax

时间:2015-10-25 10:00:53

标签: haskell

我正在寻找一个Haskell函数,它将一个列表作为参数并返回一个元组(min,max),其中min是列表的最小值,max是最大值。

我已经有了这个:

maxMinFold :: Ord a => [a] -> (a, a)
maxMinFold list = foldr (\x (tailMin, tailMax) -> (min x tailMin) (max x tailMax)) -- missing part

你能帮我解决缺失的部分吗? (或者告诉我我做错了什么)

非常感谢

4 个答案:

答案 0 :(得分:5)

你拿起头部,用它作为第一分钟最大,然后折叠在尾部。

maxMinFold :: Ord a => [a] -> (a, a)
maxMinFold (x:xs) = foldr (\x (tailMin, tailMax) -> (min x tailMin, max x tailMax)) (x,x) xs

关于你的答案,你的折叠功能没有返回正确的类型。

请注意

foldr :: (a -> b **-> b**) -> b -> [a] -> b

特别需要返回b,这是你案例中的元组

答案 1 :(得分:2)

由于您总是需要遍历整个列表以找到最小值,因此这里的最大值是foldl的解决方案:

maxMinList :: Ord a => [a] -> (a,a)
maxMinList (x:xs) = foldl (\(l,h) y -> (min l y, max h y)) (x,x) xs

答案 2 :(得分:1)

使用foldr

高效完成此操作
data NEList a = NEList a [a]
-- deriving (Eq, Ord, Show, Read, Functor, Foldable, Traversable)

minMax :: Ord a => NEList -> (a, a)
minMax (NEList x0 xs) = foldr go (,) xs x0 x0 where
  go x r mn mx
    | x < mn = r x mx
    | mx < x = r mn x
    | otherwise = r mn mx

另一种类似的方法:

minMaxM :: Ord a => [a] -> Maybe (a, a)
minMaxM xs = foldr go id xs Nothing where
  go x r Nothing = r (Just (x, x))
  go x r mnmx@(Just (mn, mx))
    | x < mn = r (Just (x, mx))
    | mx < x = r (Just (mn, x))
    | otherwise = r mnmx

答案 3 :(得分:0)

如果minMax函数在空列表的情况下返回Nothing,那将是很好的。这是一个版本。

import Control.Arrow
import Data.Maybe
import Data.Foldable

minMax :: (Ord a) => [a] -> Maybe (a,a)
minMax = foldl' (flip $ \ x -> Just . maybe (x,x) (min x *** max x)) Nothing

这使用foldl'代替foldr