在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之后,我需要帮助返回列表的其余元素。
答案 0 :(得分:2)
您可以使用累加器参数(以下代码中的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
但是,我认为了解第一种方法和如何使用累加器参数很重要,因为它在函数编程中很常见,在这种情况下您无法修改值。您会发现很多“列表”模块功能都是在某个地方使用累加器实现的。
答案 1 :(得分:1)
来自sashang的答案假定内置的F#list
类型。由于该问题似乎在案例E
和L
中使用了自定义类型,因此这里给出的答案完全不依赖于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
重要的是,此功能将有效地反转列表的顺序。如果需要保留列表的顺序,则可以增强功能以支持该要求。