List 是否从列表中删除重复项,但不在SWI Prolog中返回两个相同的结果?
我写这个谓词是为了从列表中删除replicate,但是当我测试它时List 是否从列表中删除重复项,但不在SWI Prolog中返回两个相同的结果?,list,prolog,duplicates,List,Prolog,Duplicates,我写这个谓词是为了从列表中删除replicate,但是当我测试它时 duplicate([],[]). duplicate([A|B],[A|B1]) :- not(member(A,B)), duplicate(B,B1). duplicate([A|B],List) :- member(A,B), duplicate(B,List). 有没有办法只保留一个结果,而不是两个相同的结果?(因此它将只返回一个列表) 此外,我不允许使用修改回溯搜索的运算符,例如剪切运算符!,否定运算符not、+,
duplicate([],[]).
duplicate([A|B],[A|B1]) :- not(member(A,B)), duplicate(B,B1).
duplicate([A|B],List) :- member(A,B), duplicate(B,List).
有没有办法只保留一个结果,而不是两个相同的结果?(因此它将只返回一个列表)
此外,我不允许使用修改回溯搜索的运算符,例如剪切运算符!,否定运算符not、+,或带有->和的if-then-else运算符
如果有人能帮助我,我将不胜感激D这里有一种方法可以删除所有重复项,虽然不是最有效的方法,但我认为很容易理解其意图
?- duplicate([a,b,c,a,d,c,b,a,e,f],N).
N = [d, c, b, a, e, f] ;
N = [d, c, b, a, e, f] ;
false.
如果您打算将列表编成一组:
rm_duplicates(In, Out) :-
exclude(has_duplicate(In), In, Out).
has_duplicate(List, Case) :-
dif(I, J),
nth0(I, List, Case),
nth0(J, List, Case).
它被记录为:收到多个答案的实际原因是目标
成员(A,As)
。它为As
中的重复项生成多个答案
list_to_set(List, Set).
有几种解决办法
memberchk/2
或一次/1
memberchk/2
定义为
?- member(a, [a,a]).
true
; true.
这将删除备选答案。但是,它也可能会删除其他有效的解决方案。考虑:
memberchk(X, Xs) :-
once(member(X, Xs)).
因此memberchk/2
对精确的实例化非常敏感,这使得它成为一个非常脆弱、不纯净的谓词
但它有一个优点:它只针对一个问题给出了一个答案
?- memberchk(X, [a,b]), b = X.
false.
?- b = X, memberchk(X, [a,b]), b = X.
b = X.
所以理想的定义是既纯粹又坚持第一个元素。进入
memberd/2
在此定义中,递归规则仅在列表元素不同时才具有相关性。因此,此规则永远不会应用于成员d(a[a,a,a])
您定义中的另一个问题是not(成员(A,B))
,如果A
和B
被充分实例化,则该问题只会按预期的方式运行。您的定义因以下原因而失败:
重复([a,X],[a,b])。
尽管有一个解决方案:X=b
而不是用新的方法来取代它
P>可选的,如果您对最有效的解决方案感兴趣,请考虑<代码>库(RIF)< /代码>
对于
和
这导致:
memberd(X, [X|_Ys]).
memberd(X, [Y|Ys]) :-
dif(X, Y),
memberd(X, Ys).
使用
memberchk/2
代替member/2
。也可以使用\+
而不是而不是/1
,因为前者是ISO Prolog,后者是不推荐使用的。另外,仅供参考,只有剪切修改了搜索过程。请注意排除/3
有一个隐式剪切,它会生成错误的答案,例如:B=B,rmu重复([a,B],Cs)。
成功,而rmu重复([a,B],Cs).
failsOh,谢谢,我用memberchk解决了这个问题。再次感谢您的回答!
memberd(X, [X|_Ys]).
memberd(X, [Y|Ys]) :-
dif(X, Y),
memberd(X, Ys).
list_nub([], []).
list_nub([X|Xs], Ys0) :-
if_(memberd_t(X, Xs), Ys0 = Ys1, Ys0 = [X|Ys1]),
list_nub(Xs, Ys1).