如何比较 Prolog 中的两个列表?

How to compare two lists in Prolog?

我正在尝试编写一个程序,它接受一个包含列表的列表,然后比较其中的列表。如果任何两个列表包含相同的信息,例如它们都包含 X,那么我想从两个列表中删除 X。我该怎么做?

这似乎可以做到:

dedupe(Lists, Result) :-
    append(Lists, Flat),
    findall(E, (select(E, Flat, FlatNoE), \+ memberchk(E, FlatNoE)), Uniques),
    subtract(Flat, Uniques, Unwanted),
    findall(Rs, (member(Ls, Lists), subtract(Ls, Unwanted, Rs)), Result).

例如

?- dedupe([[1,2,3], [1,2,5,6,1], [4,1,2,1]], R).
R = [[3], [5, 6], [4]]

设计是:

  • 我们需要从每个子列表中删除重复项
  • 通过查找所有元素、查找唯一元素并从所有元素中删除这些元素而留下重复元素来找到重复项。
  • 通过使用 append/2.
  • 展平嵌套列表找到所有元素
  • 通过使用 select 一次取出一个元素并查看该元素是否仍然存在于具有 memeberchk 的其余值中来找到唯一元素。
  • subtract 执行 list-from-list 减法以从所有元素中删除唯一元素,留下 Unwanted 重复元素。
  • 最后一个 findall 然后对子列表运行减法,从每个子列表中删除重复项。

在 SWI Prolog 中可以将最后一行重写为:

maplist({Unwanted}/[Ls, Ls_]>>subtract(Ls, Unwanted, Ls_), Lists, Result).

首先。在小型测试中,他们有几乎相同的 timing/inferences 要解决。