Prolog发现并删除谓词

时间:2013-02-25 12:07:06

标签: prolog

我的代码是:

locdiff([A|T], [A|_], T).
locdiff([H|T], L2, [H|T2]) :-
    locdiff(T, L2, T2). 

当我使用locdiff([(a,1), (b,2), (b,3), (c,3), (c,4)], [(b,_)], L3)对其进行测试时,它只会查找并删除[(b,_)]中的一个(b,2)。我需要它来查找和删除(b,2)(b,3)[(b,_)]包含的内容。谁能帮我解决我错过的事情?

2 个答案:

答案 0 :(得分:0)

可能你需要这样的东西:

locdiff([], _, []).

locdiff([(b,_)|T], [(b,_)], T1) :-
    !, locdiff(T, [(b,_)], T1).

locdiff([H|T], L2, [H|T2]) :-
    locdiff(T, L2, T2).

但为什么要写[A | _]如果列表中只有一个元素吗?

[编辑]我忘记了!在第二条规则中

答案 1 :(得分:0)

如果你跟随larsman'有一个值得注意的技术复杂性。提示,我会以这种方式直接实施

locdiff([], _, []).
locdiff([A|T], [A|_], R) :-
    !, locdiff(T, [A|_], R).
locdiff([H|T], L2, [H|T2]) :-
    locdiff(T, L2, T2).

用这个

?- locdiff([(a,1), (b,2), (b,3), (c,3), (c,4)], [(b,_)], L3).
L3 = [ (a, 1), (b, 3), (c, 3), (c, 4)].

你可以看到第一个实例被删除,而最后一个实例被删除。这是因为第一个匹配绑定匿名变量,然后禁止跟随匹配,但最后一个(b,_)

除外

然后完成的程序将会读取

locdiff([], _, []).
locdiff([H|T], [A|_], R) :-
    \+ \+ H = A,  % double negation allows matching without binding
    !, locdiff(T, [A|_], R).
locdiff([H|T], L2, [H|T2]) :-
    locdiff(T, L2, T2).

现在结果就是你要求的。

或者,您需要在模式匹配中更精确,避免过度绑定

locdiff([], _, []).
locdiff([(A,_)|T], [(A,_)|_], R) :-
    !, locdiff(T, [(A,_)|_], R).
locdiff([H|T], L2, [H|T2]) :-
    locdiff(T, L2, T2).

?- locdiff([(a,1), (b,2), (b,3), (c,3), (c,4)], [(b,_)], L3).
L3 = [ (a, 1), (c, 3), (c, 4)].

请注意,某些库具有特定功能,例如SWI-Prolog中的exclude / 3,但您仍需注意避免绑定:

eq([(E,_)|_], (E,_)).
locdiff(L, E, R) :-
  exclude(eq(E), L, R).