Erlang-递归删除

Erlang- Recursive Delete

我正在用 erlang 编写一个递归函数,给定一个元素 X 和一个列表,从列表中删除元素 X 并 returns 新列表。我相信我写的是正确的,但是,当我 运行 对其进行测试时,我陷入了无限循环..

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 的新手(这是我使用该语言的第二个项目),所以故障排除对我来说有点困难,但如果有人能提供一些指导,我将不胜感激。提前致谢!

首先,我不知道您为什么需要第二个子句。基本上是说 "If the first item in the list matches the item to be removed, through the whole list away and return an empty one".

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

中所有出现的 X
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).
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>