Prolog从列表中删除多个元素

时间:2011-05-23 08:11:04

标签: list prolog

我知道如何从列表中删除元素但是有没有办法从列表中删除多个元素?例如,

deletelist([a,b,c,a,b],[a,c],X)
X = [b,b] % delete a and c from the list.

5 个答案:

答案 0 :(得分:5)

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).

答案 1 :(得分:3)

要删除多个元素,我们检查一个元素是否在第二个列表中,并在条件为真时将其删除:

deletelist([], _, []).                  
deletelist([X|Xs], Y, Z) :- member(X, Y), deletelist(Xs, Y, Z), !.
deletelist([X|Xs], Y, [X|Zs]) :- deletelist(Xs, Y, Zs).

答案 2 :(得分:1)

这是一个始终产生正确答案(模终止)的定义:

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: Out of global stack

?- deletelist(Xs, Xs, Xs).
Xs = [] ;
ERROR: Out of local stack

答案 3 :(得分:0)


% sorry!

deletelist(Xs,Ys,Zs) :-
        findall(A,(
                    member(A,Xs),
                    \+(member(A,Ys))),
                Zs).

答案 4 :(得分:0)

deletelist(Xs,[],Xs).
deletelist(Xs,[Y|Ys],Zs):-
    delete(Xs,Y,As),
    deletelist(As,Ys,Zs).

要删除列表中的单个元素,可以使用库函数' delete / 3'其中包含要从该列表中删除的列表和项目,并返回删除该项目的新列表。我已经使用了这个并且重新考虑了需要从列表中删除的项目列表。