将项目列表拆分为两个奇数和偶数索引项目列表

Nat*_*ron 16 f# ocaml functional-programming tail-recursion list

我想提出一个接受列表并返回两个列表的功能:第一个是包含每个奇数项和第二个包含每个偶数项.

例如,给定[1;2;4;6;7;9],我想回来[ [1;4;7] ; [2;6;9] ].

到目前为止我写过这篇文章,我不知道如何进步.

let splitList list =
    let rec splitOdd oList list1 list2 =
        match oList with
        | [] -> []
        | head :: tail -> splitEven tail (list1::head) list2
    and splitEven oList list1 list2 =
        match oList with
        | [] -> []
        | head :: tail -> splitOdd tail list1 (list2::head)
    splitOdd list [] []
Run Code Online (Sandbox Code Playgroud)

Ed'*_*'ka 40

没有堆栈溢出的实现:

let splitList list = List.foldBack (fun x (l,r) -> x::r, l) list ([],[])
Run Code Online (Sandbox Code Playgroud)

  • 值得注意的是,'foldBack`将列表转换为数组以允许从头到尾的遍历.这通常是一件好事,因为数组遍历很快,但是对于更大的列表应该考虑成本. (8认同)

pad*_*pad 12

如果你指的是项目位置的奇数和偶数值,这里是一个(非尾递归)解决方案:

let rec splitList = function
    | [] -> [], []
    | [x]-> [x], []
    | x1::x2::xs -> let xs1, xs2 = splitList xs
                    x1::xs1, x2::xs2
Run Code Online (Sandbox Code Playgroud)

  • 这个实现的问题是,不是尾递归,它会导致~80000元素列表上的堆栈溢出. (2认同)

Gen*_*ski 6

这是一个简单的非递归解决方案:

let splitList ll =
    ll
    |> List.mapi (fun i x -> (i % 2 = 0, x))
    |> List.partition fst
    |> fun (odd,even) -> [List.map snd odd, List.map snd even];;

val splitList : 'a list -> 'a list list
Run Code Online (Sandbox Code Playgroud)

应用于您的样本,它可以产生您想要的结果:

splitList [1;2;4;6;7;9];;

val it : int list list = [[1; 4; 7]; [2; 6; 9]]
Run Code Online (Sandbox Code Playgroud)