鉴于二郎山,如任何列表:
L = [foo, bar, foo, buzz, foo].
我怎么能只显示该列表的唯一项目,使用递归函数? 我不希望使用内置的功能,如名单功能之一(如果存在的话)。
在我的例子,我想要去将是一个新的列表,如
SL = [bar, buzz].
我的猜测是,我会用快速排序功能,应用过滤器之前,首先对列表进行排序,?
任何的意见都将会有帮助。 这个例子是在利尼的&Thompson的优秀“Erlang编程”一书的第3章练习的变化。
鉴于二郎山,如任何列表:
L = [foo, bar, foo, buzz, foo].
我怎么能只显示该列表的唯一项目,使用递归函数? 我不希望使用内置的功能,如名单功能之一(如果存在的话)。
在我的例子,我想要去将是一个新的列表,如
SL = [bar, buzz].
我的猜测是,我会用快速排序功能,应用过滤器之前,首先对列表进行排序,?
任何的意见都将会有帮助。 这个例子是在利尼的&Thompson的优秀“Erlang编程”一书的第3章练习的变化。
我提出这一个:
unique(L) ->
unique([],L).
unique(R,[]) -> R;
unique(R,[H|T]) ->
case member_remove(H,T,[],true) of
{false,Nt} -> unique(R,Nt);
{true,Nt} -> unique([H|R],Nt)
end.
member_remove(_,[],Res,Bool) -> {Bool,Res};
member_remove(H,[H|T],Res,_) -> member_remove(H,T,Res,false);
member_remove(H,[V|T],Res,Bool) -> member_remove(H,T,[V|Res],Bool).
没有被检查的元件的所有出现重复和试验结果在一项所述的member_remove函数返回并将余下的尾巴。
我可以做这种方式:)
get_unique(L) ->
SortedL = lists:sort(L),
get_unique(SortedL, []).
get_unique([H | T], [H | Acc]) ->
get_unique(T, [{dup, H} | Acc]);
get_unique([H | T], [{dup, H} | Acc]) ->
get_unique(T, [{dup, H} | Acc]);
get_unique([H | T], [{dup, _} | Acc]) ->
get_unique(T, [H | Acc]);
get_unique([H | T], Acc) ->
get_unique(T, [H | Acc]);
get_unique([], [{dup, _} | Acc]) ->
Acc;
get_unique([], Acc) ->
Acc.
使用两个累加器。 一个让你看到,到目前为止,一个持有实际结果的要素。 如果您看到该项目的第一次(而不是在看表)预先准备的项目这两个列表和递归。 如果你以前见过的项目,递归之前,从你的结果(ACC)将其删除。
-module(test).
-export([uniques/1]).
uniques(L) ->
uniques(L, [], []).
uniques([], _, Acc) ->
lists:reverse(Acc);
uniques([X | Rest], Seen, Acc) ->
case lists:member(X, Seen) of
true -> uniques(Rest, Seen, lists:delete(X, Acc));
false -> uniques(Rest, [X | Seen], [X | Acc])
end.
我觉得想法可能是:请检查您是否已经看到列表的头部。 如果是这样,跳过它,递归检查尾部。 如果没有 - 现任添加到结果,以“看到”并递归检查尾部。 检查如果你已经看到该项目最合适的结构设置。
所以,我提出以下几点:
remove_duplicates(L) -> remove_duplicates(L,[], sets:new()).
remove_duplicates([],Result,_) -> Result;
remove_duplicates([Head|Tail],Result, Seen) ->
case sets:is_element(Head,Seen) of
true -> remove_duplicates(Tail,Result,Seen);
false -> remove_duplicates(Tail,[Head|Result], sets:add_element(Head,Seen))
end.
该解决方案只从列表中过滤掉重复。 可能需要在让它做你想做的建设。
remove_duplicates(List)-> lists:reverse(removing(List,[])). removing([],This) -> This; removing([A|Tail],Acc) -> removing(delete_all(A,Tail),[A|Acc]). delete_all(Item, [Item | Rest_of_list]) -> delete_all(Item, Rest_of_list); delete_all(Item, [Another_item| Rest_of_list]) -> [Another_item | delete_all(Item, Rest_of_list)]; delete_all(_, []) -> [].
编辑
Microsoft Windows [Version 6.1.7601] Copyright (c) 2009 Microsoft Corporation. All rights reserved. C:\Windows\System32>erl Eshell V5.9 (abort with ^G) 1> List = [1,2,3,4,a,b,e,r,a,b,v,3,2,1,g,{red,green},d,2,5,6,1,4,6,5,{red,green}]. [1,2,3,4,a,b,e,r,a,b,v,3,2,1,g, {red,green}, d,2,5,6,1,4,6,5, {red,green}] 2> remove_duplicates(List). [1,2,3,4,a,b,e,r,v,g,{red,green},d,5,6] 3>
试试下面的代码
-module(util).
-export([unique_list/1]).
unique_list([]) -> [];
unique_list(L) -> unique_list(L, []).
% Base Case
unique_list([], Acc) ->
lists:reverse(Acc);
% Recursive Part
unique_list([H|T], Acc) ->
case lists:any(fun(X) -> X == H end, T) of
true ->
unique_list(lists:delete(H,T), Acc);
false ->
unique_list(T, [H|Acc])
end.
唯一的(L) - >集:to_list(套:from_list(L))。
unique(List) ->
Set = sets:from_list(List),
sets:to_list(Set).
最简单的方法是使用功能与跟踪你已经拥有的元素的“蓄电池”。 所以,你会写这样一个函数
%unique_acc(累加器,List_to_take_from)。
你仍然可以有一个干净的功能,通过不出口蓄能器版本,而是出口它的调用者:
-module(uniqueness).
-export([unique/1]).
unique(List) ->
unique_acc([], List).
如果从采取列表是空的,你就大功告成了:
unique_acc(Accumulator, []) ->
Accumulator;
如果它不是:
unique_acc(Accumulator, [X|Xs]) ->
case lists:member(X, Accumulator) of
true -> unique_acc(Accumulator, Xs);
false -> unique_acc([X|Accumulator], Xs)
end.
2个注意事项:
-这确实使用列表BIF - lists:member/2
。 您可以轻松地写出这样自己,虽然。
- 元素的顺序颠倒过来,从最初的名单所致。 如果你不喜欢这个,你可以定义unique/1
的lists:reverse(unique_acc([], List))
甚至更好,自己写一个反向的功能! (这很简单)。