Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Recursion F在列表中多次插入元素_Recursion_F# - Fatal编程技术网

Recursion F在列表中多次插入元素

Recursion F在列表中多次插入元素,recursion,f#,Recursion,F#,我对F非常陌生,目前正在学习递归 let rec insert v i l = match i, l with | 0, xs -> v::xs | i, x::xs -> x::insert v (i - 1) xs;; 这是在列表l的第i个位置插入v的代码 我想重复这个过程,这样我就可以在列表l的第I个位置插入v 例如,如果我编译以下代码: insert 7 2 [1..10];; 我希望结果列表为: [1; 2; 7; 3; 4; 7; 5; 6;

我对F非常陌生,目前正在学习递归

let rec insert v i l =
    match i, l with
    | 0, xs -> v::xs
    | i, x::xs -> x::insert v (i - 1) xs;;
这是在列表l的第i个位置插入v的代码

我想重复这个过程,这样我就可以在列表l的第I个位置插入v

例如,如果我编译以下代码:

insert 7 2 [1..10];; 
我希望结果列表为:

[1; 2; 7; 3; 4; 7; 5; 6; 7; 7; 8; 7; 9; 10; 7]

当从原始代码开始时,可以使用类似的方法:

  let insert v i l =
    let rec insert2 v i p l =
      match i, l with
      | _, [] -> [v]
      | 0, xs -> v::(insert2 v p p xs)
      | i, x::xs -> x::insert2 v (i - 1) p xs
    insert2 v i i l
首先,您的原始代码有一个不完整的模式匹配警告。在F中,修复警告是很重要的,因为它们几乎总是指会导致代码失败的常规情况。对于您的函数,如果您在空列表中调用它,它将失败:insert 1[]


为了处理您描述的情况,当位置返回到0时,再次在位置i处插入一个值就足够了。当列表变为空时,递归就结束了。我引入了p变量以保持插入元素的原始位置。为此,我引入了一个私有函数insert2,只是为了保持insert方法签名不变。

从原始代码开始时,可以使用类似的方法:

  let insert v i l =
    let rec insert2 v i p l =
      match i, l with
      | _, [] -> [v]
      | 0, xs -> v::(insert2 v p p xs)
      | i, x::xs -> x::insert2 v (i - 1) p xs
    insert2 v i i l
首先,您的原始代码有一个不完整的模式匹配警告。在F中,修复警告是很重要的,因为它们几乎总是指会导致代码失败的常规情况。对于您的函数,如果您在空列表中调用它,它将失败:insert 1[]


为了处理您描述的情况,当位置返回到0时,再次在位置i处插入一个值就足够了。当列表变为空时,递归就结束了。我引入了p变量以保持插入元素的原始位置。为此,我引入了一个私有函数insert2,只是为了保持insert方法签名不变。

如前所述,您应该注意F编译器警告。不完整的模式匹配甚至会向您显示模式未涵盖的输入示例。你的情况是1,[]。如果只插入一次值,则当源列表为空时,代码将中断。但当您想要多次递归地插入值时,检查空列表是非常重要的,因为它是短路递归的基本情况

在多次插入值时,应该考虑的另一件事是,在再次插入值之前,重置要跳过的项目数。如果不将i的原始值存储在某个地方,就不能这样做。您可以将第4个参数引入函数insert v i l,但更好的解决方案是使用非递归的包装器函数。包装器函数将捕获初始i值和应插入的v值。请注意,捕获的值对内部递归函数可见

let insert v i l = // non-recursive wrapper function
    let rec skipAndInsert skip list =
        match skip, list with
        | _, [] -> [] // short-circuit recursion when there is no items left
        | 0, _ -> v::skipAndInsert i list // nothing to skip, insert value and reset skip
        | _, head::tail -> head::skipAndInsert (skip - 1) tail

    skipAndInsert i l

insert 7 2 [1..10] |> printfn "%A" // [1; 2; 3; 7; 4; 5; 6; 7; 7; 8; 9; 7; 10]

如前所述,您应该注意F编译器警告。不完整的模式匹配甚至会向您显示模式未涵盖的输入示例。你的情况是1,[]。如果只插入一次值,则当源列表为空时,代码将中断。但当您想要多次递归地插入值时,检查空列表是非常重要的,因为它是短路递归的基本情况

在多次插入值时,应该考虑的另一件事是,在再次插入值之前,重置要跳过的项目数。如果不将i的原始值存储在某个地方,就不能这样做。您可以将第4个参数引入函数insert v i l,但更好的解决方案是使用非递归的包装器函数。包装器函数将捕获初始i值和应插入的v值。请注意,捕获的值对内部递归函数可见

let insert v i l = // non-recursive wrapper function
    let rec skipAndInsert skip list =
        match skip, list with
        | _, [] -> [] // short-circuit recursion when there is no items left
        | 0, _ -> v::skipAndInsert i list // nothing to skip, insert value and reset skip
        | _, head::tail -> head::skipAndInsert (skip - 1) tail

    skipAndInsert i l

insert 7 2 [1..10] |> printfn "%A" // [1; 2; 3; 7; 4; 5; 6; 7; 7; 8; 9; 7; 10]

请注意,这实际上并不是在原始列表中插入值,而是创建一个包含附加值的新列表。原始列表将保持不变-在函数式语言中理解这一点很重要。请注意,这并不是在原始列表中插入值,而是创建一个包含附加值的新列表。原始列表将保持不变-这对于理解函数式语言很重要。