【问题标题】:F# Function that Edits a List编辑列表的 F# 函数
【发布时间】:2017-01-31 18:34:08
【问题描述】:

我正在尝试实现一个函数,该函数接受一个元素和一个列表并删除所述元素。

这没有产生输出,我不知道为什么。我是 F# 的新手,所以我很可能犯了一个基本错误。请注意,我正在尝试使用递归来做到这一点。

【问题讨论】:

  • 仅此一项只是坐在那里等待调用的函数。您需要使用 remove (3, [1..5]) 之类的名称来调用它。
  • 当我尝试这样调用它时,我得到“终端进程以退出代码终止:1”。我不知道如何解决这个问题。
  • 它是递归的,因为您在函数内部再次调用它。但是我刚刚发现了一个错误,它可能导致进程因堆栈溢出而终止:在匹配表达式的中间情况下,它应该是remove (item, tl)。您当前正在再次传入原始列表,这会导致递归永远不会终止。
  • 抱歉所有问题,您知道为什么它只会删除元素的第一次迭代吗?例如,如果我运行 remove (2, [1;2;3;2;4]) 函数在应该返回 [1;3;4] 时返回 [1;3;2;4]
  • 您也可以对已接受的答案进行投票。 :)

标签: list f#


【解决方案1】:

试试这个。

let rec remove item lst =
    let rec removeInner item lst acc =
       match lst with
       | h::tl when item = h -> removeInner item tl acc
       | h::tl -> removeInner item tl (h::acc)
       | []    -> List.rev(acc)
    removeInner item lst []

[<EntryPoint>]
let main argv = 

    let result = remove 2 [1;2;2;3;4;2]
    printfn "%A" result

    0

这没有产生输出,我不知道为什么。

您的版本没有生成输出的原因是因为这一行

| []    -> []

内容为:当列表为空时,返回一个空列表。

您需要做的是将未删除的值累加起来,并将累加的值作为结果返回。

在 F# 中使用累加器对于初学者来说是典型的,并且是使用此行创建的。

removeInner item lst []

末尾的[] 是累加器,它是一个空列表,因为您没有向其中添加任何内容。

然后随着你的进步,你用这一行添加它

| h::tl -> removeInner item tl (h::acc)

最后你将累加器中的值反转并用这一行返回

| []    -> List.rev(acc)

【讨论】:

  • 您可以使用CPS。本质上,在每次调用时递归地传递一个函数,并在退出递归的过程中调用该函数,将项目附加到列表中。由于项目以正确的顺序附加到列表中,因此无需反转它们。有点高级,但你可以做到。有趣的是,我刚刚使用Prolog 回答了类似的问题,但是使用 Prolog,您不会传递函数,而是传递了 difference list
  • 您可以使用列表追加运算符@,但追加到列表末尾效率不高。 F# 第三方库之一创建了差异列表,但我找不到。
  • 感兴趣的:The Continuation Passing Transform and the Yoneda Embedding 如果您正在上课,请向您的老师询问这件事,看看会发生什么。
【解决方案2】:

我不知道你的问题的意图是什么,是真的删除还是在列表上写了一些递归函数。

实现你想要的最简单的方法是:

let remove item lst = List.filter (fun x -> x <> item)

即:过滤掉所有与你的item相等的元素

这有帮助吗?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-02-12
    • 1970-01-01
    • 2012-05-28
    • 1970-01-01
    • 1970-01-01
    • 2014-10-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多