我正在尝试编写一个将列表拆分为两个的方法。该函数应返回两个列表的元组,函数所采用的参数是第一个列表中的项目数,然后是列表。这就是我的意思
列表[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语句来暂时保存我正在构建的列表。这是语言的新手,所以有几种不同的方法可以学习。
答案 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)