如何在出现函数最大值的列表中查找值 [英] How to find the value in a list at which a maximum value of a function occurs
问题描述
我不仅要查找应用于列表的函数的最大值(我将仅使用List.maxBy),还要找到出现在列表中的值.感觉这是一个相当普通的操作,并且考虑到F#库的丰富程度,总的来说我发现它实际上已经可用并不会感到惊讶,但是如果有的话,我似乎找不到它!
I want to find not just the maximum value of a function applied to a list (for which I would just use List.maxBy) but also the value in the list this occurred at. This feels like a fairly common operation and given the richness of the F# libraries in general I wouldn't be at all surprised to discover it was actually already available but I cannot seem to find it if it is!
为了举例说明,我希望能够映射列表domain
和函数f
To illustrate with an example, I want to be able to map a list domain
and a function f
let domain = [0 .. 5]
let f x = -x * (x - 2)
到(1, 1)
(因为应用于列表其他元素的函数小于1).
to (1, 1)
(since the function applied to an other element of the list is less than 1).
我首先尝试过:
let findMaximum domain f =
let candidates = [ for x in domain do
yield x, f x ]
let rec findMaximumHelper domain f currentMax =
match domain with
| [] -> currentMax
| head::tail ->
let cand = f head
match currentMax with
| None ->
let newMax = Some(head, cand)
findMaximumHelper tail f newMax
| Some(maxAt, possMax) ->
let newMax =
if cand > possMax then Some(head, cand)
else Some(maxAt, possMax)
findMaximumHelper tail f newMax
findMaximumHelper domain f None
let answer = findMaximum domain f
这时我意识到这与 fold 操作非常接近,并将其放在一起
at which point I realised this is very close to a fold operation, and put together
let findMaximum2 domain f =
let findMaximumHelper f acc x =
let cand = f x
match acc with
| None -> Some(x, cand)
| Some(maxAt, possMax) ->
if cand > possMax then Some(x, cand)
else Some(maxAt, possMax)
List.fold (findMaximumHelper f) None domain
let answer2 = findMaximum2 domain f
相反.
我的问题是,这些惯用的F#方法是否可以解决此问题,或者确实有更好的方法来解决此问题?
My question is, are these idiomatic F# ways of solving this problem, or indeed, is there a better way of solving this?
推荐答案
实际上,F#库提供了所有必要的高阶函数来简洁地表达这一点:
Indeed, the F# library provides all the necessary higher order functions to express this succinctly:
domain
|> Seq.map (fun x -> x, f x)
|> Seq.maxBy snd
注意:已更新为使用Seq.map
和Seq.maxBy
而不是List.map
和List.maxBy
来解决@ildjarn关于创建不必要的中间列表的担忧.
Note: updated to use Seq.map
and Seq.maxBy
instead of List.map
and List.maxBy
to address @ildjarn's concern about creating an unnecessary intermediate list.
这篇关于如何在出现函数最大值的列表中查找值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!