了解删除重复项时在列表末尾打印



我一直在尝试通过编写一个简单的程序来学习Prolog,该程序给定一个项目列表,并以相同的顺序返回/存储列表的副本,而不重复。例如:[1,1,2,3,3,5]返回[1,2,3,5]。我使用append将数字添加到一个空列表中,并使用成员检查是否已经添加了整数。

remove_duplicates([], R). 
remove_duplicates([H|T], R) :-
member(H, R)
-> remove_duplicates(T, R)
;  append(H, R),
remove_duplicates(T, R).

我已经让代码几乎可以工作了,但是当运行代码时,它会返回R=[1,2,3,6|_]。我尝试过跟踪和调试,但我不明白为什么最后会添加|_

我对代码的思考过程如下,如果我误解了什么,请指出。

remove_duplicates([], R). % If first list is empty, return R. (Used to stop the recursion).
remove_duplicates([H|T], R) :-
member(H, R)
-> remove_duplicates(T, R) % If head is member of R (=true), call remove:_duplicates again without the head. 
;  append(H, R),
remove_duplicates(T, R). % else (if member(H, R) = false), add the head to list R and call remove_duplicates again with tail and R. 

我对实现一个prolog谓词的问题的回答很接近,该谓词删除了@brebs所指出的所有重复元素,但它不会提供您想要的内容。这个

list_set( []     , []     ) .
list_set( [X|Xs] , Ys     ) :- memberchk(X,Xs), !, list_set(Xs,Ys) .
list_set( [X|Xs] , [X|Ys] ) :-                     list_set(Xs,Ys) .

更喜欢重复项目的最后,因此

[1,2,3,3,2,1]

降低到

[3,2,1]

这违反了你的问题陈述中的约束,即你得到

列表的副本,没有相同顺序的重复项。

我们可以通过使用带有累加器的辅助谓词并引入append/3:的使用,将其切换为首选任何重复元素中的第一个

list_set( Xs , Ys ) :- list_set( Xs , [] , Ys ) .
list_set( []     , Ys , Ys ) .
list_set( [X|Xs] , Ts , Ys ) :- memberchk(X,Ts)   , ! , list_set(Xs,Ts,Ys) .
list_set( [X|Xs] , Ts , Ys ) :- append(Ts,[X],T1) ,     list_set(Xs,T1,Ys) .

这是迄今为止我发现的最快的方法(不使用appendreverse(:

https://stackoverflow.com/a/74024975/

最新更新