我想从prolog中先前排序的列表中删除多个重复项。我希望输出看起来像这样:
示例1。
?- remove_dups ([1,1,2,2,3,4,5,5,6], List).
List = [3,4,6]
正如你所看到的,它不会删除相同元素的重复,而是全部删除。
我使用了以下算法,我做了一些修改但没有成功。 这是我使用的算法:
remove_dups([], []).
remove_dups([X], [X]).
remove_dups([X,X|T], [X|R]) :-
remove_dups([X|T], [X|R]).
remove_dups([X,Y|T], [X|R]) :-
X \== Y,
remove_dups([Y|T], R).
remove_dups([X,Y|T], [X|R]) :-
( X == Y
-> remove_dups([Y|T], [X|R])
; remove_dups([Y|T], R)
).
然而,我对此算法的输出是这样的。
?- remove_dups([1,1,2,2,3,4,5,5,6], List).
List = [1,2,3,4,5,6]
但我希望它与示例1中的任何提示相同?
答案 0 :(得分:3)
这与Include non-unique elements only非常相似,可以非常类似地解决。
我再次使用if_//3
来保留关系的一般性:请注意,通常可以在多个方向中使用有用的Prolog谓词,因此像remove_dups/2
这样的命令式名称不适合表达其他方向和更一般的用例。
相反,我将称之为 list_singulars/2
的关系,并将其定义为:
list_singulars(Ls0, Ls) :- phrase(list_singulars(Ls0, []), Ls). list_singulars([], _) --> []. list_singulars([L|Ls], Ls0) --> if_((memberd_t(L, Ls);memberd_t(L, Ls0)), [], [L]), list_singulars(Ls, [L|Ls0]).
这是一个简单的测试用例:
?- list_singulars([a,a,b], List). List = [b].
你发布的例子:
?- list_singulars([1,1,2,2,3,4,5,5,6], List). List = [3, 4, 6].
此外,我们还可以使用更多常规查询生成答案:
?- list_singulars([a,X], List). X = a, List = [] ; List = [a, X], dif(X, a).
请注意使用dif/2
,这是一种真正的关系。有关详细信息,请参阅prolog-dif。
以下是最常规查询:
?- list_singulars(Ls0, Ls). Ls0 = Ls, Ls = [] ; Ls0 = Ls, Ls = [_6826] ; Ls0 = [_6826, _6826], Ls = [] ; Ls0 = [_6826, _6826, _6826], Ls = [] ; Ls0 = [_6826, _6826, _6826, _6826], Ls = [] .
我们可以通过迭代加深轻松获得公平枚举:
?- length(Ls0, _), list_singulars(Ls0, Ls). Ls0 = Ls, Ls = [] ; Ls0 = Ls, Ls = [_7798] ; Ls0 = [_7798, _7798], Ls = [] ; Ls0 = Ls, Ls = [_8436, _8442], dif(_8442, _8436) ; Ls0 = [_7798, _7798, _7798], Ls = [] ; Ls0 = [_8494, _8494, _8506], Ls = [_8506], dif(_8506, _8494) .
答案 1 :(得分:0)
当您检测到重复项,即与[X,X|T]
统一时,请从列表中删除剩余的X
:
remove_dups([], []).
remove_dups([X], [X]).
remove_dups([X,Y|T], [X|R]) :-
X \= Y,
remove_dups([Y|T], R).
remove_dups([X,X|T], R) :-
skip(X, T, WithoutX),
remove_dups(WithoutX, R).
正如您所看到的,您非常接近:remove_dups/2
规则的第1,第2和第3条来自您的代码。唯一的区别在于最后一个子句,它在递归之前会跳过X
的剩余值。
skip/2
谓词可以按如下方式实现:
skip(_,[],[]).
skip(X, [X|T], T).
skip(X, [Y|T], [Y|T]) :- X \= Y.