从列表中删除重复项和原始文件

时间:2015-03-15 16:32:17

标签: list prolog

我编写了一些代码来删除列表中的所有重复项,以便remove_duplicates([1,2,3,4,5,3,4,5], L).获取L = [1, 2, 3, 4, 5].

member1(X,[H|_]) :- 
    X==H,!.
member1(X,[_|T]) :- 
    member1(X,T).

remove_duplicates([],[]).       
remove_duplicates([H|T],X) :- 
    member1(H,T),                
    !,                          
    remove_duplicates(T,X).     

remove_duplicates([H|T],[H|X]) :- 
    remove_duplicates(T,X).

我想要做的是删除副本并删除原件,以便remove_duplicates([1,2,3,4,5,3,4,5], L).获取L = [1, 2].,其中3,4和5将被移除。

3 个答案:

答案 0 :(得分:1)

这是remove_duplicates的一种方法,但它不是尾递归的。

remove_duplicates([],[]).

remove_duplicates([H|T], X) :-
    remove_duplicates(T,X1),
    (   member(H, X1)
    ->  select(H, X1, X)
    ;   X = [H |X1]).

是的,我的第一个代码不正确,因为我没有记住重复。这是一个正确的解决方案:

remove_duplicates(In, Out) :-
    remove_duplicates(In, _, Out).

remove_duplicates([],[], []).

remove_duplicates([H|T], Dup, X) :-
    remove_duplicates(T,Dup1, X1),
    (   member(H, Dup1)
    ->  X = X1,
    Dup = Dup1
    ;   (   member(H, X1)
    ->  select(H, X1, X),
        Dup = [H | Dup1]
    ;   X = [H | X1],
        Dup = Dup1)).

我们得到了

 ?- remove_duplicates([1,2,3,2,1,2,3,4,5], L).
L = [4, 5] ;
false.

答案 1 :(得分:0)

而不是member1 / 2,你可以使用select / 3,所以元素被删除,然后涓流其余的参数:

remove_duplicates([],[]).       
remove_duplicates([H|T],X) :- 
    select(H,T,R),                
    !,                          
    remove_duplicates([H|R],[H|X]).
remove_duplicates([H|T],[H|X]) :- 
    remove_duplicates(T,X).

编辑事实证明,代码是错误的,例如,在?- remove_duplicates([2,2,2],X).上失败了:这里是一个修正

remove_duplicates([],[]).       
remove_duplicates([H|T],X) :- 
    select(H,T,R),                
    !, findall(X, (member(X, R), X\=H), NotH),
    remove_duplicates(NotH, X).
remove_duplicates([H|T],[H|X]) :- 
    remove_duplicates(T,X).

答案 2 :(得分:0)

我有这个:

remove_duplicates(List, NewList):-
 once(remove_duplicates(List,[],[],NewList)).


remove_duplicates([],_ACALL,Ac,Ac).

remove_duplicates(List,ACALL,Ac,NewList):-
 List= [H|T],
 member(H,ACALL),
 select(H,Ac,NewAc),
 remove_duplicates(T,ACALL,NewAc,NewList).

remove_duplicates(List,ACALL,Ac,NewList):-
 List= [H|T],
 member(H,ACALL),
 remove_duplicates(T,ACALL,Ac,NewList).


remove_duplicates(List,ACALL, Ac,NewList):-
 List =[H|T],
 not(member(H,ACALL)),
 remove_duplicates(T,[H|ACALL],[H|Ac],NewList).

我使用两个累加器,一个用于记录所有看到的项目(ACALL),另一个用于返回当前列表..这是一个很好的方法吗?