2012-02-03 55 views
1

我有一個序列,我需要找到序列的最小值以及該序列中該值的索引 - 有效地某種「Seq.mini」功能沿Seq.mapi或Seq.iteri行。函數不僅可以找到序列的最小值,而且還可以找到F#中的索引號

在F#中表達這種乾淨/最習慣的方式是什麼?

在習慣上,我應該期待寫一個函數返回一個元組(值,索引)或(索引,值),如果有的話是否有約定這些值應該出現的順序?另一件事:如果有多個具有相同最小值的元素,我需要首次出現的索引 - 我想這將轉化爲嚴格的「小於(<)」比較,而不是「小於或等於(< =)「 - 正確嗎?

回答

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 
+0

非常感謝!我能夠將這與Ramon的答案中的元組函數結合起來,以取代lambda,使其看起來可讀並且有意義(對我來說) – 2012-02-03 13:02:54

+1

只是一個想法:如果函數是mini的第一個參數,第二個是序列,將與F#集合函數一致,'let mini fs = s |> Seq.mapi(fun ix - >(i,x))|> Seq.minBy f' – 2012-02-03 14:00:36

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

+0

我不知道怎麼稱呼這個 - 抱歉,我是f#新手。我不得不定義元組並解除自己(這些元素不是內置的),以擺脫編譯器錯誤,但它們非常直截了當。但我仍然不確定如何調用它。此外,我實際上有一個列表,而不是一個序列,但這是行不通的:miniBy seq myList – 2012-02-03 12:24:54

+0

這有助於:'Seq.miniBy(有趣的索引值 - > 2 *索引+值)[1..5]' ?生成的類型將是'int * int'(一個來自索引的「int」,另一個來自該值)。 – 2012-02-03 12:40:34

+1

添加了編輯,顯示元組,uncurry以及如何調用該函數的示例。 – Robert 2012-02-03 12:44:46

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) 
相關問題