将列表元素与索引配对

Pairing list elements with indexes

给定一个元素列表,我需要将每个元素转换为一对索引号和元素。有几种方法可以做到;这是迄今为止我发现的最简洁的:

List.mapi (fun i x->i,x) xs

但是有没有更concise/idiomatic的方法呢?例如,F# 是否有一些内置函数可以将两个元素变成一对,一些等效于 C++ make_pair?

标准库中有一个函数可以做到这一点:List.indexed

编写索引的八种方法

因为有不止一种方法可以做到这一点 (TIMTOWTDI),了解不同的方法及其优缺点总是好的。请记住,解决问题的方法永远不会只有一种。这里有一些例子,如果你试着去理解它们,你可以从中学习。

1。列表理解

let indexed1 xs =
    let mutable idx = 0
    [ for x in xs do
        yield idx,x
        idx <- idx + 1 ]

2。紫平啦!

let indexed2 xs =
    List.zip
        (List.init (List.length xs) id)
         xs

3。递归

let indexed3 xs =
    let rec cata idx xs =
        match xs with
        | []    -> []
        | x::xs -> (idx,x) :: cata (idx+1) xs
    cata 0 xs

4。 Tail-Recursion

let indexed4 xs =
    let rec loop idx result xs =
        match xs with
        | []    -> result
        | x::xs -> loop (idx+1) ((idx,x) :: result) xs
    List.rev (loop 0 [] xs)

5。折叠起来

let indexed5 xs =
    let mutable idx = -1
    List.fold (fun state x ->
        idx <- idx + 1
        (idx,x) :: state
    ) [] xs
    |> List.rev

6。不可变的折叠

let indexed6 xs =
    List.fold (fun (idx,state) x ->
        (idx+1), (idx,x) :: state
    ) (0,[]) xs
    |> snd
    |> List.rev

7。向后折叠

let indexed7 xs =
    let lastIdx = List.length xs - 1
    List.foldBack (fun x (idx,xs) ->
        (idx-1), ((idx,x) :: xs)
    ) xs (lastIdx,[])
    |> snd

8。排列

let indexed8 xs =
    let arr = Array.ofList xs
    let mutable result = []
    for idx=(arr.Length - 1) downto 0 do
        result <- (idx,arr.[idx]) :: result
    result