使用递归反转列表

时间:2014-03-10 10:50:36

标签: erlang

我正在写一本关于Erlang的书。这是任务:在不使用BIF的情况下编写反向函数。

这就是我的所作所为:

reverse([H | T]) -> [reverse(T) | [H]];
reverse([]) -> [].

以下是此函数返回的内容:

(emacs@localhost)3> examples:reverse([1, 2, 3]).
[[[[],3],2],1]

我无法理解如何让它返回展平列表[3, 2, 1]。它有可能吗?

4 个答案:

答案 0 :(得分:4)

在语法[H | T]中,H是一个元素,T是一个列表(至少对于proplist),在你的代码中[reverse(T) | [H]]创建一个列表,其中第一个元素是{{1}的结果},以及哪个tail是单个元素列表reverse(T)

如果你想以这种方式实现这个功能,你应该使用fenollp提出的语法。

如果你想编写一个有效的代码,你应该避免对部分结果进行多个中间复制,并避免使用non tail recursive calls(为了限制调用堆栈的大小:

[H]

答案 1 :(得分:3)

正如你所说,你只需要压扁。

所以要么使用列表:在你的例子之后追加/ 1:反向/ 1函数,或用reverse([H | T]) -> [reverse(T) | [H]];替换reverse([H | T]) -> reverse(T) ++ [H];

然后,代码在算法上效率非常低,这就是为什么列表:reverse / 1,2是BIF。

答案 2 :(得分:1)

你可以使用折叠:

lists:foldl(fun(X, Acc) -> [X | Acc] end, [], [1,2,3]).

答案 3 :(得分:0)

您不必将结果放在列表中。 这对我来说很好:

reverse([]) -> [];
reverse([H | T]) -> reverse(T) ++ [H].