Prolog减去列表统一

时间:2012-02-28 07:09:51

标签: prolog

我试图在prolog中从另一个列表中减去一个列表。在我的程序中,输入列表中有空格(例如[1,2,_,4])

我得到以下输出:

?- subtract([1,2,3,4],[3,4,_],L).

L = [2].

当我想要输出

L = [1,2].

所以我的问题是如何防止空格与其他元素统一?已经坚持了一段时间。

3 个答案:

答案 0 :(得分:1)

假设您希望忽略“空格”,您可以简单地删除每个列表的版本并计算它们的差异:

listWOblanks( [], [] ).
listWOblanks( [H|T], Tx ) :- var(H), !,  listWOblanks( T, Tx ).
listWOblanks( [H|T], [H|Tx] ) :- listWOblanks( T, Tx ).

如果,当第一个列表有空白而第二个列表没有空白时,你需要结果仍然有空白,你可以修改上面的内容来添加第三个参数,告诉你是否删除了任何空格以便你可以纠正相应的差异。我相信SWI-Prolog有一个谓词,它会告诉你一个术语中是否没有变量,这样就无需修改listWOblanks。

答案 1 :(得分:0)

larsmans是正确的,_匿名变量lists:subtract/3的定义(我假设你在SWI-Prolog中使用)将会始终将它们统一到地面列表成员,因为它使用memberchk/2定义。

如果您希望subtract行为将变量视为基础术语,那么您可以像这样重新定义:

subtract2([], _, []) :- !.
subtract2([A|C], B, D) :-
    var_memberchk(A, B), !,
    subtract2(C, B, D).
subtract2([A|B], C, [A|D]) :-
    subtract2(B, C, D).

请注意,此处的subtract2/3lists:subtract/3的定义几乎相同(请尝试listing(subtract).自行查看)。唯一的区别是列表成员谓词var_memberchk/2,其定义如下:

var_memberchk(A0, [A1|_]) :- 
    A0 == A1, !.
var_memberchk(A0, [_|R]) :- 
    var_memberchk(A0, R).

这将检查变量,原子或术语是否在列表中。所以,试试这个我们得到:

?- subtract2([1,2,3,4],[3,4,_],L).
L = [1, 2].

请注意,如果我们按照您的预期命名变量,它仍然有效:

?- subtract2([1,2,A,3,B,4],[3,A,4],L).
L = [1, 2, B].

如果我们明确地给匿名变量命名,它也可以工作,如:

?- subtract2([1,2,_A,3,_B,4],[3,_A,4],L).
L = [1, 2, _B].

最后请注意,由于_没有名称,subtract2/3 永远不会能够将其与任一列表中的其他匿名变量相匹配,例如:

subtract2([1,2,_,4],[3,_,4],L).
L = [1, 2, _G415].

其中_G415是由第一个输入列表中的_表示的匿名全局变量。第二个是不同的全局变量(例如_G416),因此永远不会匹配第一个列表中的匿名变量。

答案 2 :(得分:0)

另一种方式:

% Uses list catenation to generate sublists /subtraction
conc([], L, L).

conc([X|L1], L2, [X|L3]) :-
    conc(L1, L2, L3).

% Finds all list members that have values and then
% use list catenation to generate the sublists
subtract(L1, L2, L3) :-
   findall(D, (nth0(N, L2, D), nonvar(D)), PureL2),
   conc(L3, PureL2, L1).

这假设只有一个列表有'_',但如果两个列表都有相同的问题,你可以为L1做同样的findall。