【问题标题】:How to write a recursion function in haskell如何在haskell中编写递归函数
【发布时间】:2013-04-10 06:15:18
【问题描述】:

如何在 Haskell 中编写一个函数,该函数接受一个列表和一个数字,然后删除所有大于该数字的元素并返回该列表。

删除 [5, 4, 3, 9, 1 ] 5 应该返回 [5,4,3,1]

我写了下面的方法,当它达到大于给定的数字时,它会变成无限循环。我要出去 [5,4,3 然后程序没有结束。

remove l1 x = if (null l1 == True)
                then l1
                else if (head l1 > x)
                       then remove (drop 0 l1) x
                       else ((head l1) : remove (tail l1) x)

这是我第一次尝试 Haskell 程序,请建议我在这里做错了什么。

谢谢

【问题讨论】:

  • 你得到了无限循环,因为 then remove (drop 0 l1) x 你在同一个列表中重复出现,drop 的第一个参数表示要删除多少元素,你输入错误 drop 0 而不是 drop 1你需要。

标签: haskell


【解决方案1】:

嗯,你的开端不错,但重要的是要注意,你并没有采取最“Haskell”的方法。

让我向您展示解决此问题的几种不同方法:

方法一:递归函数

首先,我们可以编写一个递归函数(就像你一样)来解决这个问题。

为此,我们首先适应一个基本情况(在正常情况下不允许无限循环)。这应该有效:

remove [] _ = []

这只是说,如果我们要从一个空列表中删除元素,我们最终会得到一个空列表。就是这么简单。 _ 表示我们不在乎 x 是什么值。

现在我们必须定义其他情况。为此,我会使用警卫(我确信还有其他方法,也添加了基本情况以完成):

remove [] _ = []
remove (x:xs) y
 | x > y     = remove xs y
 | otherwise = x : remove xs y

所以,第一行 (remove (x:xs) y) 表示我们的函数将采用一个列表(其中x 是头/第一个值,xs 是其余的)。

第二行是说,如果x 大于y,则考虑其余元素,我们不认为x 是我们最终解决方案的一部分。

第三行(otherwise 捕获所有情况,如果命中,就像其他语言中的 if/elseif/else 条件块中的 else)。如果我们到了这一点,我们知道x > y 不是真的,所以我们考虑其余的值(xs)并包括x,但现在我们已经完成了x

现在,这种方法效果不错,但还有一种更简单的方法:

方法 2:列出理解

使用list comprehensions,我们可以构建一个非常简单、强大的解决方案:

remove xs y = [x | x <- xs, not (x > y)]

如果您曾经研究过set-theory(特别是set-builder notation),那么您应该会觉得很熟悉。让我们来看看每个部分的含义。

  • [...] - 括号中的内容仅表示我们正在构建一个列表

  • x |... - 表示我们的列表将包含xs 使得(| 表示“这样”)...

  • x &lt;- xs, - xxs 的一个元素并且(逗号表示“和”)...

  • not (y &gt; x) - y 大于 x 是不正确的

如您所见,第二种方法几乎完全模仿了您对问题的描述。这确实是 Haskell 的强大功能,文字和抽象几乎可以直接映射到 Haskell 代码中。

方法3:使用filter

正如下面的评论所说,第三种选择是这样定义它:

remove y = filter (<=y)

where 过滤器只会保留小于或等于 y 的元素。 (此方法归功于 Daniel Wagner)。

【讨论】:

  • ...或者只是remove y = filter (&lt;=y)
  • 是的,好点。我看到另一个答案这么说并给了他们+1。
【解决方案2】:

您可以在函数 args 中使用模式匹配并使用警卫进行过滤:

remove []    x = []
remove (h:t) x | h > x = remove t x
               | otherwise = h : remove t x

您也可以使用函数filter,它可以满足您的需求:

remove l x = filter (<= x) l

【讨论】:

    猜你喜欢
    • 2016-08-13
    • 2013-04-21
    • 2011-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多