如何在haskell的列表中获取最短列表

时间:2013-10-26 14:23:08

标签: list haskell compare

此函数接收列表列表并返回最短的列表(如果列表列表为空,则返回空列表)

例如,

最短[[1,2,9],[3,4],[1,2,3,5]] 将返回[3,4]

shortest :: [[a]] - > [α]

我对haskell的新任何帮助将不胜感激 感谢

4 个答案:

答案 0 :(得分:8)

  

前奏> :m + Data.List
  Prelude Data.List> :m + Data.Function
  Prelude Data.List Data.Function> minimumBy(compare`on`length)[[1,2,9],[3,4],[1,2,3,5]]
  [3,4]

它如何运作 - 好吧,minimum非常明显。但是我们不想通过默认的词典排序来比较数字列表,而是我们想要指定确切地比较什么属性 - 即长度。 compare`on`ᴘʀᴏᴘᴇʀᴛʏ是一个简单的记忆通用技巧,它使用

Data.Function.on :: (b->b->c) -> (a->b) -> a->a->c
compare :: Ord a => a -> a -> Ordering

所以(compare`on`)Ord b => (a->b) -> a->a->Ordering,即如果我们可以提供一个产生可比属性的函数,我们就会获得任何数据类型的比较函数。在我们的例子中,那是length

最后,我们需要使用该排序来实际选择最小元素。执行技巧is Data.List.minimumBy的功能。


请注意,此解决方案效率不高:它会将length多次应用于每个列表。您不应该使用它来查找数千个中最短的列表,每个列表包含数百个元素。当然存在更好的算法,但它们并不简单和简洁。

答案 1 :(得分:4)

我想扩展@leftaroundabout提供的解决方案。

Prelude Data.List Data.Function> minimumBy (compare `on` (map . const $ 1)) [[1..],[5..11],[3,4]]

与原始解决方案不同,这个解决方案肯定适用于无限列表。

答案 2 :(得分:3)

shortest [y] = y    --base case: if there's only one element left, return it.
shortest (x:y:lst)  --extract the first two elements x, y from the list.  
    | length x > length y = *recursion*  
    | otherwise = *recursion*

您可以使用递归来解决此问题。 我基本上为你列出了结构,但你应该考虑如何实现递归部分。记住,当函数调用自身时会发生递归。

提示:使用冒号将最短元素连接回原始列表,以便将其与列表中的下一个元素进行比较。

希望它有所帮助!

答案 3 :(得分:0)

首先,您需要从Data.Ord进行比较

import Data.Ord

然后给出minimumBy比较函数,按长度比较

minimumBy (comparing (length)) [[1,2,9],[3,4],[1,2,3,5]]