检索元组中最大的第一个组件

时间:2013-11-25 00:52:20

标签: haskell

重要的是,我必须警告我正在学习Haskell,而且我不知道预先构建的许多函数,所以我将使用到目前为止学到的东西。

我写过这个,我能做的最好的方法,尝试了很多但却无法通过。

minFst :: [(t, t1)] -> [(t, t1)]
minFst [] = []
minFst ((a,b):(a1,b1):xs) = if (a >= a1) then (a,b): minFst xs
                                         else (a1,b1): minFst xs

这个功能需要的是:

[(10,21), (3, 55), (66,3)] = [3,55]  -- Gives me the tuple with the lowest 'a'

编辑:在删除ord函数的建议之后,只有当我调用minFst时才会给我编译错误:

minFst [(1,2),(4,5),(5,7),(2,5),(10,6)]
[(4,5),(5,7)*** Exception: Helder.hs:(584,1)-(586,72): Non-exhaustive patterns in function minFst

我希望你可以帮助我解决这个问题,如果这篇文章有问题,请告诉我,我会改变它,不要一开始就贬低我。

1 个答案:

答案 0 :(得分:4)

使用一些内置函数Data.List.minimumByData.Ord.comparingfst非常简单:

import Data.List (minimumBy)
import Data.Ord (comparing)

minFst :: Ord a => [(a, b)] -> (a, b)
minFst xs = minimumBy (comparing fst) xs

或者你可以点免费地写它

minFst = minimumBy (comparing fst)

既然你说你不能将这些功能用于你的任务,那么让我们自己编写一个简单的最小函数

myMin :: Ord a => [a] -> a
myMin [] = error "Empty list!"
myMin [x] = x
myMin (x:y:xs) = if x < y then myMin x xs else myMin y xs

现在,这不适用于您的情况,因为您想要找到具有最小元素的元组,因此您必须稍微修改此代码

myMin :: Ord a => [(a, b)] -> (a, b)
myMin [] = error "Empty list!"
myMin [x] = x
myMin ((a1, b1):(a2, b2):xs) = {- Implementation here -}

我会让你自己填写。现在,如果想要所有具有最小第一个元素的元组(可能有多个元素),您可以通过首先计算最小值,然后过滤具有第一个元素的所有列表来低效地执行它。这不是最好的算法,因为你必须两次搜索列表。


如果你想一次性完成,它会变得有点棘手。在这些情况下,您希望在遍历时累积当前最小值。每当你需要累积值时,你需要另一个参数,但最好将它隐藏在本地函数内,而不是模块级函数中。我将向您展示一个整数列表的示例:

minimums :: [Int] -> [Int]
minimums xs = go xs []
    where
        go [] acc = acc
        go (x:xs) (y:ys)
            | x == y = go xs (x:y:ys)  -- Accumulate the x
            | x < y  = go xs [x]       -- Reset if new min found
            | otherwise = go xs (y:ys) -- Ignore x if greater than y

> minimums [1, 2, 3, 2, 1]
[1, 1]

对于Int来说并不是很令人兴奋,但它会为您提供使用元组执行此操作所需的基本模式。像内置minimum一样,这个函数不能是懒惰的,它必须评估列表中的每个元素,所以不要将它传递给无限列表,否则你将永远等待它完成。< / p>