我正在尝试学习如何以函数式编程方式思考,为此,我正在学习Erlang并解决来自codingbat的简单问题。我遇到了比较列表中元素的常见问题。例如,将第i个位置元素的值与列表中第i+1个位置的值进行比较。因此,我一直在思考和搜索如何以函数式方式在Erlang(或任何函数式语言)中完成这项任务。
请温柔地对待我,我是这个函数式世界中的新手,但我想学习。
提前致谢。
请温柔地对待我,我是这个函数式世界中的新手,但我想学习。
提前致谢。
定义一个列表:
L = [1,2,3,4,4,5,6]
定义一个名为f的函数,该函数接受一个列表作为参数。
Erlang代码如下
f ([]) -> [];
f ([_]) -> [];
f ([X, X|Rest]) -> [X | f(Rest)];
f ([_|Rest]) -> f(Rest).
应用函数
f(L)
这个应该可以工作...我还没有编译和运行它,但是它可以让你开始。如果你需要对它进行修改以使它表现不同,也可以这样做。
欢迎来到Erlang ;)
我试着温柔一些;-) 函数式编程的主要思路是考虑输入和输出。没有仅仅比较第 i 个元素和第 i+1 个元素的情况。必须总是有一个目的,这将导致数据转换。即使 Mazen Harake 的示例也是如此。在这个例子中,有一个函数,它仅返回由相同值后跟的元素,即过滤给定列表。通常有非常不同的方式来做类似的事情,这取决于它的目的。列表是基本的函数结构,就像 Lisp 向我们展示的那样,您可以用它做出惊人的事情,但您必须记住它不是数组。
每次需要访问第i个元素时,如果需要重复操作,则说明您正在使用错误的数据结构。在Erlang中,您可以从列表和元组构建不同的数据结构,以更好地满足您的需求。因此,当您遇到比较第i个和第i+1个元素的问题时,您应该停下来思考一下。它的目的是什么?您需要执行一些流数据转换,就像Mazen Harake所做的那样,还是需要随机访问?如果是后者,您应该使用不同的数据结构(例如array)。即使如此,您也应该考虑您的任务特性。如果您大多数情况下只读取而几乎不写入,则可以使用list_to_tuple(L)
,然后使用element/2
进行读取。当您需要偶尔写入时,您将开始考虑将其分成几个元组,并且随着您的写入比率增长,您最终将使用array
实现。
如果您只需要对短列表执行一次或几次操作,并且不像我一样非常注重性能,那么可以使用lists:nth/2
。 您可以使用[X1,X2|_] = lists:nthtail(I-1, L)
来改善它(L = lists:nthtail(0,L)
的预期效果)。 如果您面对更大的列表并且想要多次调用它,则必须重新考虑您的方法。
P.S.:除了列表和树之外,还有许多其他迷人的数据结构。例如Zippers。