好吧,你已经有了一个不错的开始,但重要的是要注意你没有采取最“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
如果命中则捕获所有情况,就像其他语言的条件块中else
的 an )。if/elseif/else
如果我们到了这一点,我们知道这是不正确的,x > y
所以我们考虑其余的值 ( xs
) 并包括x
,但我们现在已经完成了x
。
现在,这种方法效果不错,但还有一种更简单的方法:
方法 2:列出理解
使用列表推导,我们可以构建一个非常简单、强大的解决方案:
remove xs y = [x | x <- xs, not (x > y)]
如果您曾经研究过集合论(特别是集合构建符号),那么您应该会觉得这很奇怪。让我们来看看每个部分的含义。
[...]
- 括号中的内容仅表示我们正在构建一个列表
x |...
- 意味着我们的列表将包含x
s 这样(|
意味着“这样”)......
x <- xs,
-x
是xs
and 的一个元素(逗号的意思是“和”)...
not (y > x)
- 大于是不正确y
的x
如您所见,第二种方法几乎完全模仿了您的问题描述。这确实是 Haskell 的强大功能,文字和抽象往往几乎直接映射到 Haskell 代码中。
方法 3:使用filter
正如以下评论所述,第三种选择是将其定义为:
remove y = filter (<=y)
其中过滤器只会保留小于或等于 y 的元素。(这种方法归功于 Daniel Wagner)。