我一直发现自己想要一个功能,我总是需要自己实现它,但我觉得必须有内置功能。</ p>
基本上,我想要的是maximum
和maximumBy
之间的中间位置。
maximum
获取Ord
值列表并返回最大值。这是O(n)。
maximum :: (Ord a) => [a] -> a
maximumBy
获取非Ord
值列表和一个为它们排序的排序函数,并使用该函数计算最大值。这是O(nlogn)(或者无论其复杂程度如何)。
maximumBy :: (a -> a -> Ordering) -> [a] -> a
我希望maximumBy
获取类型a
的值列表和返回Ord
值的a
值的函数,并计算最大值{{1}使用a
值。这将是O(n),因为它只需跟踪最大值。这就是签名:
Ord
这是我粗略的实施:
maximumBy' :: (Ord b) => (a -> b) -> [a] -> a
是否内置了这样的功能,或者使用现有内置函数编写此功能的简单方法?
答案 0 :(得分:5)
首先,你提出错误的说法:
maximumBy
获取非Ord值列表和为它们提供排序的sort函数,并使用该函数计算最大值。这是 O(nlogn)。
不需要进行排序来计算最大元素。排序关系必须是自反,反对称和传递,因此,到目前为止,人们可以简单地保持最大值,并使用自定义比较以检查新项目是否更大。
此外,您可以将maximumBy'
函数构建为:
maximumBy' f = maximumBy (compare `on` f)
答案 1 :(得分:4)
我认为您正在寻找的内容可以使用Data.Ord.comparing
:
而不是使用maximumBy'
功能:
maximumBy' head ["abc", "def", "geh"]
您可以使用comparing
构建一个比较器并将其提供给通常的maximumBy
:
maximumBy (comparing head) ["abc", "def", "geh"]
正如Willem Van Onsem在另一个回答中所说的那样,关注maximumBy
的费用是不正确的:它不会对列表进行排序。
答案 2 :(得分:4)
该函数被定义为the tip-lib
package为
maximumOn :: (Foldable f, Ord b) => (a -> b) -> f a -> b
一般的想法也是adopted in recent base
, with
sortOn :: Ord b => (a -> b) -> [a] -> [a]
请注意,由于懒惰,您可以使用
maximumOn :: Ord b => (a -> b) -> [a] -> b
maximumOn f = head . sortOn f
并获得与手动实现相同的渐近性能。
答案 3 :(得分:1)
我不知道任何内置函数可以执行您想要的操作,但您可以真正简化maximumBy'
的实现。
您可以使用on
例如:
import Data.Function (on)
maximumBy' :: Ord b => (a -> b) -> [a] -> a
maximumBy' f = maximumBy (compare `on` f)
事实上,这个定义非常简单,您可以按原样使用它,而不必定义maximumBy'
。