我需要一些我正在尝试创建的例程的帮助。我需要制作一个看起来像这样的例程:
difference([(a,b),(a,c),(b,c),(d,e)],[(a,_)],X).
X = [(b,c),(d,e)].
我真的需要帮助...
到目前为止,我已经编写了一个方法,可以删除它找到的第一个匹配项。但是我需要它来删除所有出现的事件。这是我到目前为止所拥有的......
memberOf(A, [A|_]).
memberOf(A, [_|B]) :-
memberOf(A, B).
mapdiff([], _, []) :- !.
mapdiff([A|C], B, D) :-
memberOf(A, B), !,
mapdiff(C, B, D).
mapdiff([A|B], C, [A|D]) :-
mapdiff(B, C, D).
我已从列表(减去)中获取此代码。
我不完全明白它的作用,但我知道这几乎是我想要的。我没有使用减法因为我的最终代码必须与WIN-Prolog兼容......我正在SWI Prolog上测试它。
答案 0 :(得分:4)
整蛊一个! 简陋的咖啡有正确的想法。这是一个使用双重否定的奇特解决方案:
difference([], _, []).
difference([E|Es], DL, Res) :-
\+ \+ member(E, DL), !,
difference(Es, DL, Res).
difference([E|Es], DL, [E|Res]) :-
difference(Es, DL, Res).
适用于SWI-PROLOG。说明:
第1条:基本案例。什么都不反对!
第2条:如果E在差异列表DL中,member/2
子目标评估为true
,但我们不希望接受member/2
在存在的变量之间的绑定例如,在任一列表中,就像我们所希望的那样,术语(a,_)
中的变量可以在其他术语中重用,而不是绑定到第一个解决方案。因此,第一个\+
会删除成功评估member/2
所创建的变量绑定,第二个\+
会根据需要将评估状态反转为true
。检查后发生切割,排除第3个子句,并丢弃统一的元素。
第3条:在两个清单中保留任何不可统一的要素。
答案 1 :(得分:3)
我不确定,但这样的事情可行。您可以使用findall
查找无法与模式统一的所有元素:
?- findall(X, (member(X, [(a,b),(b,c),(a,c)]), X \= (a,_)), Res).
获得回复
Res = [ (b, c) ]
所以
removeAll(Pattern, List, Result) :-
findall(ZZ109, (member(ZZ109, List), ZZ109 \= Pattern), Result).
应该有效,假设ZZ109
不是Pattern
中的变量(遗憾的是,我不知道为此获取新变量的方法。可能有一个不可移植的变量WIN-序言)。然后可以递归地定义difference
:
difference(List, [], List).
difference(List, [Pattern|Patterns], Result) :-
removeAll(Pattern, List, Result1),
difference(Result1, Patterns, Result).
答案 2 :(得分:2)
您可以轻松修改代码,使其成为memberOF
谓词只是检查列表中是否有可以统一的元素而不实际统一它的代码。在SWI Prolog中,可以这样做:
memberOf(A, [B|_]) :- unifiable(A,B,_).
但我不熟悉WIN-PRolog所以不知道它是否有一个谓词或运算符只测试参数是否可以统一。