Erlang-递归删除

时间:2015-02-25 18:35:00

标签: recursion erlang

我正在努力在erlang中编写一个递归函数,给出一个元素X和一个列表,从列表中删除元素X并返回新列表。我相信我已经正确地写了它,然而,当我对它进行测试时,我被抛入无限循环中..

delete(_,[]) -> [];
delete(X,[X|_]) -> [];
delete(X,[Y|YS]) -> 
    if X == Y -> YS;
    true -> [Y] ++ delete(X,[YS]) % I believe the infinite loop is a result of this line..
end.

我是erlang的新手(这是我使用该语言的第二个项目),因此对我来说故障排除有点困难,但如果有人能提供一些指导,我们将非常感激。提前谢谢!

2 个答案:

答案 0 :(得分:2)

首先,我不知道为什么你需要第二个条款。基本上它会说"如果列表中的第一项与要删除的项匹配,则通过整个列表离开并返回一个空的"。

最简单的方法是从列表开始,使用空列表存储结果。然后,当我们遍历列表中的项目时,我们会添加与结果不匹配的项目,并忽略与我们要删除的项目匹配的项目。这将删除X中出现的所有List

delete(X, List) -> delete(X, List, []). % Provide the same API as before

delete(_,[], Result) -> Result; % If the list is empty we are done.
delete(X,[Y|YS], Result) -> 
  case X == Y of
    true ->
      delete(X,[YS], Result);
    false -> 
      delete(X,[Y|YS], Result)
  end.

但为什么不使用lists:filter/2?它使它更简单:

delete(X, List) ->
  lists:filter(fun(Item) ->
    Item /= X
  end, List).

答案 1 :(得分:2)

delete(_,[]) -> []; %% ok removing anything from an empty list gives an empty list
delete(X,[X|_]) -> []; %% big mistake. If you find the element you want to remove on top
                       %% of the list, you must remove it and continue with the rest of the list
delete(X,[Y|YS]) -> 
    if X == Y -> YS;   %% this will never occurs since you already test this case
                       %% in the previous clause. An the result should be delete(X,YS), not YS.
    true -> [Y] ++ delete(X,[YS]) %% correct
end.

我没有看到你有无限循环的地方,但是第二个句子会使递归调用停止得太早。

所以你的代码应该是:

delete(_,[]) -> [];
delete(X,[X|Rest]) -> delete(X,Rest);
delete(X,[Y|YS]) -> [Y] ++ delete(X,[YS]).

但我会建议使用列表推导来实现非常短的代码和快速执行(这是列表中使用的代码:filter / 2):

delete(X,L) -> [Y || Y <- L, Y =/= X].
%              ^        ^       ^
%              |        |       |_ when Y different from X
%              |        |_________ with all the elements Y from L
%              |__________________ make a list

在shell中定义函数,得到:

1> D = fun D(_,[]) -> [];       
1>         D(X,[X|R]) -> D(X,R);
1>         D(X,[Y|R]) -> [Y] ++ D(X,R) end.
#Fun<erl_eval.36.90072148>
2> D(4,[1,2,3,4,5,6]).
[1,2,3,5,6]
3> D1 = fun(X,L) -> [Y || Y <- L, Y =/= X] end.
#Fun<erl_eval.12.90072148>
4> D1(4,[1,2,3,4,5,6]).                        
[1,2,3,5,6]
5>