我试图创建一个谓词,在保持列表相对顺序的同时,从列表中删除重复的内容。例如,一个列表是[1,2,2,3,4,5,5,2],应该返回[1,2,3,4,5]。但是,我的代码只能删除连续重复的内容,例如,不能删除最后的2。
remove_duplicates([],[]).
remove_duplicates([H],[H]).
remove_duplicates([H,H|T],[H|List]) :- remove_duplicates(T,List).
remove_duplicates([H,X|T],[H|T1]):- X\=H, remove_duplicates([X|T],T1).
我想到的另一个方法是用member来查看尾部是否包含头部。然而,我唯一能想到的解决方法是,如果head是tail的成员,我将删除head。然而,这将只保留数字的最后一个实例,并且打破了列表中数字的相对顺序。
比如说
[1,2,2,3,4,5,5,2]
[1,3,4,5,2]
当我真正想要的是
[1,2,3,4,5]
你可以利用一个累加器:一个额外的参数,这里的列表最初是空的,当新的元素出现时将会增长。每一次递归调用都会传递一个列表(或一个更新的副本)。
比如说
remove_duplicates(LA, LB) :-
remove_duplicates(LA, LB, []).
remove_duplicates([], [], _).
remove_duplicates([H|T], R, Seen) :-
( member(H, Seen)
-> (R = S, Seen1 = Seen)
; (R = [H|S], Seen1 = [H|Seen])
),
remove_duplicates(T, S, Seen1).
这样我们就得到了:
?- remove_duplicates([1,2,2,3,4,5,5,2], L).
L = [1, 2, 3, 4, 5].
当然,你可以使用比list更有效的数据结构。我把这作为一个练习。