【问题标题】:how to get a Shortest List in a list in haskell如何在haskell的列表中获取最短列表
【发布时间】:2013-10-26 14:23:07
【问题描述】:

这个函数接受一个列表并返回最短的一个(如果列表为空,则返回一个空列表)

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

最短 :: [[a]] -> [a]

我是 haskell 的新手,任何帮助将不胜感激 谢谢

【问题讨论】:

  • 看来这个问题已经有了一些好的答案。但是,在未来,礼貌地说出您尝试过的内容,以及您遇到困难的位置和原因。

标签: list haskell compare


【解决方案1】:

前奏曲> :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 多次应用于每个列表。您不应该使用它来从数千个列表中找到最短的列表,每个列表包含数百个元素。当然存在更好的算法,但它们并不那么简单和简洁。

【讨论】:

  • 你也可以使用Data.Ord中的comparing函数。然后你可以做minimumBy (comparing length) [[1,2,9],[3,4],[1,2,3,5]]。这也几乎读作简单的英语,这很好。
  • 好点,那是一种规范。虽然我认为“比较长度的最小值”可能比“比较长度的最小值”更接近简单的英语,而且它当然更通用(例如nubBy ((==)`on`length))。
【解决方案2】:

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

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

与最初的解决方案不同,这个解决方案绝对适用于无限列表。

【讨论】:

  • 不错!您可以缩短map . const $ 1 ≡ map $ const 1,也使 IMO 更清晰。或者更好,map $ const ()
【解决方案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*

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

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

希望对你有帮助!

【讨论】:

  • 嗯,你当然可以使用递归解决任何问题(否则,也没有其他方法)。然而,当有高阶函数可以从你身上抽象出这种负担时,使用它们通常是一个好主意。如果您对minimumBy 的超短解决方案有效率问题,您仍然可以使用折叠,这相当于您指向的显式递归解决方案。
  • 我理解您的担忧。考虑到他/她是 Haskell 的新手,我只是认为递归是要走的路。 @leftaroundabout
  • 嗯。一方面,我不同意——Haskell 的构建方式使得高阶函数特别易于使用,并且它们往往比显式递归更清晰、更容易重构等。 OTOH,在某些时候掌握递归方法是不可避免的,这可能比折叠更简单。至少Chakravarty & Keller recommend teaching recursion before higher-order solutions,所以...好的——同意,+1。
  • 谢谢 :) 我同意你的观点,Haskell 的高阶函数总体上是方便和简洁的,我也认为递归是高阶函数的基础。 @leftaroundabout
【解决方案4】:

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

import Data.Ord

然后通过按长度比较的比较函数给出最小值

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-04-03
    • 1970-01-01
    • 2021-03-07
    • 2012-01-21
    • 2017-02-27
    • 2013-05-02
    • 2022-01-25
    • 1970-01-01
    相关资源
    最近更新 更多