我知道如何从列表中删除一个元素,但是否有一种方法可以从列表中删除多个元素?例如,
deletelist([a,b,c,a,b],[a,c],X)
X = [b,b] % delete a and c from the list.
SWI-Prolog 提供了 subtract/3
函数:
?- subtract([a,b,c,a,b], [a,c], X).
X = [b, b].
?- listing(subtract).
lists:subtract([], _, []) :- !.
lists:subtract([A|C], B, D) :-
memberchk(A, B), !,
subtract(C, B, D).
lists:subtract([A|B], C, [A|D]) :-
subtract(B, C, D).
deletelist([], _, []).
deletelist([X|Xs], Y, Z) :- member(X, Y), deletelist(Xs, Y, Z), !.
deletelist([X|Xs], Y, [X|Zs]) :- deletelist(Xs, Y, Zs).
deletelist(Xs, Ys, Zs) :-
tfilter(not(list_memberd_truth(Ys)),Xs, Zs).
not(G, E, T) :-
call(G, E, NT),
( NT = true, T = false
; NT = false, T = true
).
list_memberd_truth(Xs, X, Truth) :-
memberd_truth(X, Xs, Truth).
使用其他答案中的tfilter/3
和memberd_truth/3
。 如果您的Prolog不支持dif/2
,请参见iso_dif/2
以进行安全近似。
一些更不寻常的问题仍然是正确的:
?- deletelist([a], [X], Zs).
X = a, Zs = []
; Zs = [a], dif(X, a)
; false.
?- deletelist([X], [Y], [X]).
dif(X, Y)
; false.
以下是一些应该失败(并因此终止)但却循环的查询。请注意,循环远比给出错误答案要好。
?- deletelist([a], Zs, Zs).
error(resource_error(local_stack),_).
?- deletelist(Xs, Xs, Xs).
Xs = []
; error(resource_error(local_stack),_).
% sorry!
deletelist(Xs,Ys,Zs) :-
findall(A,(
member(A,Xs),
\+(member(A,Ys))),
Zs).
deletelist(Xs,[],Xs).
deletelist(Xs,[Y|Ys],Zs):-
delete(Xs,Y,As),
deletelist(As,Ys,Zs).
要从列表中删除单个元素,可以使用一个名为'delete/3'的库函数。它接受一个列表和要从该列表中删除的项目,并返回已删除该项目的新列表。我已经利用了这个函数,并在需要从列表中删除项目的项上进行了递归。
deletelist([a],[a],[a]).
成功了,但它应该失败。 - false