【问题标题】:removing an element from a list using recursion and pattern matching使用递归和模式匹配从列表中删除元素
【发布时间】:2018-09-06 22:55:57
【问题描述】:

在 F# 中使用递归,我应该编写一个递归函数来从列表 l 中删除一个整数 n。 该函数接受 int 和 iList 并返回一个 iList(即整数列表)

这是我目前所拥有的:

let rec remove n l match l with | E -> failwith "Empty List" | L(h,E) -> if (h=n) then 0 else h | L(h,t) -> if (h=n) then remove n t else h + remove n t

在上面的代码中,我对其进行了设置,以便在从列表中排除给定整数 n 后,它返回列表中元素的总和,而不是列表中的实际元素。

在排除给定整数 n 后,我需要帮助返回列表的剩余元素。

【问题讨论】:

    标签: recursion f# pattern-matching


    【解决方案1】:

    您可以使用累加器参数(下面代码中的acc)来执行此操作。 acc参数用于携带上一次调用递归函数的结果,从而构建最终结果。这是函数式编程中的常见范例。在这种情况下,我们从一个空列表开始 acc 并向其中添加元素,但当它与 x 匹配时跳过。

    let rec remove x l acc =
        match l with
        | [] -> acc
        | h::t when x = h ->  List.append acc t
        | h::t -> remove x t (List.append acc [h])
    

    像这样使用它:

    remove 1 [1;2;3] []
    

    另一种方法是使用List.collect

    let remove_use_collect x l =
        let helper y =
            if x = y then [] else [y]
        List.collect helper l
    

    但是我认为了解第一种方法以及如何使用累加器参数很重要,因为它在函数式编程中很常见,您无法修改值。你会发现很多 List 模块的功能都是在某处使用累加器实现的。

    【讨论】:

      【解决方案2】:

      来自 sashan 的答案假定内置 F# list 类型。由于该问题似乎使用了带有案例EL 的自定义类型,因此这是一个完全不依赖于List 模块或类型的答案。它也不会将累加器作为顶级参数公开,因此调用者无需担心传递初始值:

      type ilist = E | L of (int * ilist)
      
      let remove value list =
          let rec remove value acc = function
          | E -> acc
          | L (head, tail) when head = value -> tail |> remove value acc
          | L (head, tail) -> tail |> remove value (L (head, acc))
      
          list |> remove value E
      

      作为重要说明,此功能将有效地反转列表的顺序。如果您需要保留列表的顺序,您可以增强该功能以支持该要求。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-20
        • 2015-06-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多