函数不仅可以查找序列的最小值,还可以查找F#中的索引

时间:2012-02-03 11:03:14

标签: list f# idiomatic

我有一个序列,我需要找到序列的最小值,以及序列中该值的索引 - 实际上是Seq.mapi或Seq.iteri行中的某种“Seq.mini”函数。

在F#中表达这种最干净/最恰当的方法是什么?

惯用法,我是否应该期望编写一个返回元组(值,索引)或(索引,值)的函数,如果有的话,是否存在这些值应出现在哪个顺序的约定?

另一件事:如果有多个元素具有相同的最小值,我需要第一次出现的索引 - 我想这会转换为严格的“小于(<)”比较而不是“小于”或等于(< =)“ - 正确吗?

3 个答案:

答案 0 :(得分:5)

这是一个简单的清洁解决方案:

let mini s = s |> Seq.mapi (fun i x -> (i, x)) |> Seq.minBy snd
let index, value = seq [3;6;1;5;1] |> mini

答案 1 :(得分:1)

我会考虑更多,并定义两个通常有用的函数。

(* Infinite sequence of whole numbers. 0 .. *)
let indices = Seq.unfold (fun x -> Some(x, x + 1)) 0

(* Zips the given sequence with indices of elements. *)
let zipWithIndex coll = Seq.zip coll indices

printfn "%A" ([12; 8; 9; 90; 3; 24] |> zipWithIndex |> Seq.minBy fst) // prints (3, 4)

答案 2 :(得分:0)

这个怎么样

let tuple a b = a, b
let uncurry f (a, b) = f a b

module Seq =
    let inline miniBy f seq =
        (Seq.mapi tuple
        >> Seq.minBy (uncurry f)) seq

Seq.miniBy (fun i x -> x) [ 4; 6; 3; 7; 2; 2; 7 ]

谓词函数接收索引,但在这种情况下不需要使用它。

注意: miniBy : (int -> 'a -> 'b) -> seq<'a> -> int * 'a when 'b : comparison