开发者

How to find max's index in a Seq, List or Array in F#

开发者 https://www.devze.com 2022-12-16 11:30 出处:网络
Seq.max finds the max number. I\'d like to have something like开发者_高级运维 Seq.findIndex Seq.maxIndex returns the index of the maximum element. I believe you are looking for something like:

Seq.max finds the max number. I'd like to have something like开发者_高级运维 Seq.findIndex

Seq.maxIndex returns the index of the maximum element.


I believe you are looking for something like:

let maxIndex seq = 
    fst (Seq.maxBy snd (Seq.mapi (fun i x -> i, x) seq))

Note that giving this function an empty sequence will result in an ArgumentException.

(Alternatively, written in pipelining style:

let maxIndex seq =  
    seq
    |> Seq.mapi (fun i x -> i, x)
    |> Seq.maxBy snd 
    |> fst

)


Why not simply use

let l=[1;2;5;3];;
Seq.findIndex  (fun x -> x= Seq.max l) l ;;

?

Or maybe as Johan Kullbom suggest in a comment:

"let m = Seq.max l in Seq.findIndex (fun x -> x = m) l"

if you what a little better O(n)

However, the need to get the index looks to me like a imperative "code smell" .

In FP it's usually better to use existing functions before you roll your own. I now this in the eyes of a C programmer seems like a for(i (for(j construct but I bet that you probably really don't need to know the index if you start think in FP.

More or less a duplicate of Finding index of element in a list in Haskell?

PS. I can't resist. In Haskell (ghc) the way should probably be something like

let cmpSnd (_, y1) (_, y2) = compare y1  y2

let maxIndex l= fst $ maximumBy cmpSnd $ zip [0..] l

However, since zip in F# doesn't seem to allow zip with unequal lengths of the list(?) the use of mapi is probably the way to go (my haskell version in F#)

let cmpSnd xs=  snd xs ;;

let zipIndex a= Seq.mapi (fun i x -> i,x) a;;

let maxIndex seq=fst (Seq.maxBy cmpSnd (zipIndex seq));;

and the reason is only so that I can make a list

let l= [[0;199;1];[4;4];[0;0;399]]

test with makeIndex l;; and decide that what I really want is a

let cmpSnd' (a,(xs: int list))  = Seq.sum  xs;;
let maxIndex' seq=fst (Seq.maxBy cmpSnd' (zipIndex seq));;

Now time to decomposite and make makeIndex take a function

let maxIndexF seq maxF=fst (Seq.maxBy maxF (zipIndex seq));;

val l : int list list = [[1; 2; 199]; [3; 3]; [4; 1]; [0; 299]]

> maxIndexF l cmpSnd'
;;
val it : int = 3
> maxIndexF l cmpSnd
;;
val it : int = 2

Finish it up

let maxIndexF'  maxF=fst << Seq.maxBy maxF << zipIndex ;;

maxIndexF' cmpSnd' l;;
maxIndexF' cmpSnd l;;
0

精彩评论

暂无评论...
验证码 换一张
取 消