Как найти индекс max в Seq, List или Array в F # - PullRequest
3 голосов
/ 10 января 2010

Seq.max находит максимальное число. Я хотел бы иметь что-то вроде Seq.findIndex

Seq.maxIndex возвращает индекс максимального элемента.

Ответы [ 2 ]

14 голосов
/ 10 января 2010

Я полагаю, вы ищете что-то вроде:

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

Обратите внимание, что предоставление этой функции пустой последовательности приведет к ArgumentException.

(Альтернативно, написано в стиле конвейеризации:

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

)

3 голосов
/ 10 января 2010

Почему бы просто не использовать

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

Или, может быть, как предлагает Йохан Куллбом в комментарии:

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

если вы немного лучше O (n)

Однако необходимость получения индекса выглядит для меня как императивный «запах кода» .

В FP обычно лучше использовать существующие функции перед тем, как создавать свои собственные. Теперь я вижу, что в глазах программиста на C это выглядит как конструкция for (i (for (j), но я готов поспорить, что вам, вероятно, действительно не нужно знать индекс, если вы начнете думать в FP.

Более или менее дубликат Нахождение индекса элемента в списке в Haskell?

PS. Я не могу сопротивляться. В Haskell (ghc) путь должен выглядеть примерно так:

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

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

Однако, поскольку zip в F #, по-видимому, не позволяет zip с неравной длиной списка (?), Использование mapi, вероятно, является подходящим вариантом (моя версия на haskell в 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));;

и причина только в том, что я могу составить список

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

тест с makeIndex l ;; и решить, что я действительно хочу это

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

Теперь время разложить и заставить makeIndex взять функцию

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

Готово

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

maxIndexF' cmpSnd' l;;
maxIndexF' cmpSnd l;;
...