如何在列表中找到函数最大值所在的值

  • 本文关键字:最大值 函数 列表 f#
  • 更新时间 :
  • 英文 :


我不仅想找到应用于列表的函数的最大值(为此我只使用list . maxby),还想找到列表中发生的值。这感觉像是一个相当常见的操作,并且考虑到f#库的丰富性,如果发现它实际上已经可用,我一点也不会感到惊讶,但我似乎找不到它。

为了举例说明,我希望能够映射列表domain和函数f

let domain = [0 .. 5]
let f x = -x * (x - 2)

(1, 1)(因为作用于列表中另一个元素的函数小于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
这时我意识到这非常接近于折叠操作,然后把 放在一起
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#解决这个问题的惯用方法吗?或者,确实有更好的方法来解决这个问题吗?

事实上,f#库提供了所有必要的高阶函数来简洁地表达这一点:

domain
|> Seq.map (fun x -> x, f x)
|> Seq.maxBy snd

注意:更新为使用Seq.mapSeq.maxBy而不是List.mapList.maxBy来解决@ildjarn关于创建不必要的中间列表的问题。

Stephen的答案的另一种选择,避免创建第二个List,以执行f的额外时间为代价:

domain
|> List.maxBy f
|> fun x -> x, f x

相关内容

  • 没有找到相关文章

最新更新