在维持Prolog秩序的同时去除重复的内容。

问题描述 投票:1回答:1

我试图创建一个谓词,在保持列表相对顺序的同时,从列表中删除重复的内容。例如,一个列表是[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]
list duplicates prolog logic predicate
1个回答
1
投票

你可以利用一个累加器:一个额外的参数,这里的列表最初是空的,当新的元素出现时将会增长。每一次递归调用都会传递一个列表(或一个更新的副本)。

比如说

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更有效的数据结构。我把这作为一个练习。

© www.soinside.com 2019 - 2024. All rights reserved.