如何在列表匹配谓词中找到最后一个元素的索引?

时间:2015-07-07 23:13:53

标签: f#

我想获得匹配谓词的列表中元素的最后一个索引。我知道我可以使用以下代码作为数组,但我想知道是否有办法为列表执行此操作(不转换为数组并使用以下函数):

let tryFindLastIndex f (arr: 'a []) =
    let rec loop n (arr: 'a []) =
        match n with
        | -1 -> None
        | n ->
            if f arr.[n] then Some n
            else loop (n-1) arr
    loop (arr.Length - 1) arr

2 个答案:

答案 0 :(得分:4)

我通过惯用法使用库函数和组合器来完成这项任务:

let tryFindLastIndex f ls =
    match ls |> (List.rev >> List.tryFindIndex f) with
    | None -> None
    | Some n -> Some (ls.Length - n - 1)

编辑:对于那些过度关注性能的人来说,使用库函数和组合器仍然可以通过单个列表遍历实现相同的目标清晰度:

let tryFindLastIndex f ls =
    match (ls |> List.fold (fun (i,r) l -> if f l then (i+1,i::r) else (i+1,r)) (0,[]) |> snd) with
    | [] -> None
    | x -> Some (x.Head)

答案 1 :(得分:3)

F#中的{p> list是一个链接列表,您不能轻易地在最后一个方向上进行迭代。因此,您必须从头开始迭代并保持跟踪与谓词匹配的最后一个元素的当前索引和索引。

你仍然使用本地递归函数来做到这一点。

let tryFindLastIndex f source =
    let rec loop index lastFoundIndex source =
        let newIndex = index+1
        match source with
        | [] -> lastFoundIndex
        | head :: tail ->
            if f head then loop newIndex (Some index) tail
            else loop newIndex lastFoundIndex tail
    loop 0 None source