在F#中按索引n剪切列表

时间:2013-05-23 05:10:12

标签: list f# f#-3.0 f#-scripting

尝试编写一个递归函数,用n剪切列表。然后返回2个列表。所以,如果我通过

cut(2, [5;10;4;2;7]);;
  val it : int list * int list = ([5; 10], [4; 2; 7])

我想得到类似的东西。

let rec cut (n, xs) = 
        match n, xs with 
        | 0, xt -> (n, xs)
        | n, x::xt -> cut(n, xt), xs;;

请帮忙。

2 个答案:

答案 0 :(得分:2)

我将解释@MisterMetaphors递归函数。

剪切函数不是递归的,而是辅助函数,它通过从n向下计数并从传递给cut的列表的头部删除元素来工作。

说你像这样叫cut 2 [ 3; 4; 5; 7; 8 ]。 aux是一个模式匹配函数,它带有三个参数:n,分区1,分区2.分区1以空列表开始,分区2以传递给cut的完整列表开始。

第一次aux将匹配第二个子句,然后它将使用参数(1,[3],[4; 5; 7; 8])调用自身。下次它也会匹配第二个子句,现在它用(0,[4; 3],[5; 7; 8])调用自己。第三次也是最后一次匹配第一个子句(n = 0),它将返回一个包含xs和ys的元组。

请注意,xs的元素顺序相反,因为每个元素都是前置的(使用cons运算符::)。这样做的原因是因为它是一个O(1)操作,与追加操作符@左侧的O(n)相比。

由于xs的顺序相反,函数中的最后一个表达式是xs的反转。

另一种略微简短的定义可能是:

let cut n xs =
    let rec aux = function
        | 0, xs, ys -> List.rev xs, ys
        | n, xs, y :: ys -> aux (n - 1, y :: xs, ys)
        | _ -> failwith "invalid arguments"
    aux (n, [], xs)

答案 1 :(得分:1)

最好将列表或序列上的内置函数组合起来实现这一点:

let cut' (n, xs) =
    Seq.take n xs, Seq.skip n xs

递归地,您的函数可以这样定义:

let cut (n, xs) =
    let rec aux = function
        | 0, xs, ys -> xs, ys
        | n, xs, y :: ys -> aux (n - 1, y :: xs, ys)
        | _ -> failwith "invalid arguments"
    let l, r = aux (n, [], xs)
    (List.rev l, r)