拆分列表F Sharp

时间:2014-01-25 16:48:14

标签: list f#

我正在尝试编写一个将列表拆分为两个的方法。该函数应返回两个列表的元组,函数所采用的参数是第一个列表中的项目数,然后是列表。这就是我的意思

列表[1,2,3,4]

分裂(1,列表) - > ([1],[2,3,4]) split(3,list) - > ([1,2,3],[4])

这是我到目前为止所拥有的:

let rec mysplit = function
  |(n,[])->([],[])
  |(1,x::xs)->(x::[],xs)
  |(n,x::xs)->  mysplit(n-1,xs)

我不确定如何从递归调用中“捕获”元组。不知道在哪里有一个额外的let语句来暂时保存我正在构建的列表。这是语言的新手,所以有几种不同的方法可以学习。

3 个答案:

答案 0 :(得分:6)

在这里跳过并带走你的朋友。当有直接的方法时,我认为你不需要进行任何类型的匹配或递归调用。

let split n l = (l |> Seq.take n, l |> Seq.skip n)

对于可能的边缘情况,如果列表中有> n个元素,则skip将返回空序列,如果序列中有< n个元素,则take将返回前n个元素。

使用您的示例在TryFharp.org中尝试了它,它按预期工作。

答案 1 :(得分:3)

直接的实施将是:

let rec mysplit = function
  |(n,[])->([],[])
  |(1,x::xs)->(x::[],xs)
  |(n,x::xs)->  let (f, s) = mysplit(n-1,xs) in (x::f, s)

您还可以编写尾递归版本:

let mysplit (n, l) = 
    let rec mysplit' n' (f, s) = function
    | [] -> (f, s)
    | (x::xs) as l' -> if n' = 0 then (f, l') else mysplit' (n'-1) (x::f, xs) xs

    let (f', s) = mysplit' n ([], []) l in (List.rev f', s)

答案 2 :(得分:0)

Lee的回答显示了一个有效的解决方案,但是为了回答您的具体问题,您可以在元组中捕获返回给您的值:

let before, after = mysplit (2, [1;2;3;4;5])

您还可以使用此技巧在单个let语句中声明多个变量:

let i, j, k = (1, 2, 3)