list - 在 Prolog 中删除重复项并保持顺序

标签 list duplicates prolog logic predicate

我正在尝试创建一个谓词,从列表中删除重复项,同时保持其相对顺序。例如,列表 [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 来查看 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, <b>[]</b>).

remove_duplicates([], [], <b>_</b>).
remove_duplicates([H|T], R, <b>Seen</b>) :-
    (  member(H, Seen)
    -> (R = S, <b>Seen1 = Seen</b>)
    ;  (R = [H|S], <b>Seen1 = [H|Seen]</b>)
    ),
    remove_duplicates(T, S, <b>Seen1</b>).

这给了我们:

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

当然,您可以使用比列表更有效的数据结构。我把它留作练习。

关于list - 在 Prolog 中删除重复项并保持顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61396806/

相关文章:

c++ - 从仅包含其迭代器的列表中删除元素

python - 如何获取 csv 内容的列表?

javascript - PHP 表单代码有时会同时执行两次

c - 如何复制指针以指向同一对象

prolog - 将命令纳入谓词解析

python - 如何拆分列表的元素?

string - 在 CMake 中如何将命令的多行输出转换为列表?

mysql - 如何从具有多个相同值的列的表中获取最新结果

prolog - SWI-Prolog 使用移位 CLPFD 报告错误答案

database - 如何在Prolog中进行参数搜索?