删除列表中的元素

时间:2014-10-09 15:16:22

标签: prolog

我想删除list1中的元素,当它等于list2中的元素时。 查询和预期输出是:

filter( [[1,2,3],[1]] , [[1]] , X ).
X = [[1, 2, 3]] ;

filter( [[1,2,3],[1],[2,3,4],[2]] , [[1],[2]] , X ).
X = [[1, 2, 3],[2,3,4]] ;

我现在所做的是:

filter(_,[],_). 
filter([A|B],[A|D],E):-
    filter(B,D,E).
filter([A|B],[C|D],[A|E]):-
    A\=C,
    filter(B,D,E).

但似乎不对,并给出如下输出:

11 ?- filter([[1,2,3],[1]],[[1]],X).
X = [[1, 2, 3]|_G488] ;

有人可以帮忙吗?也许我接近成功。

3 个答案:

答案 0 :(得分:0)

您的程序无法正常工作,因为您每次都会从第二个列表中删除一个元素。您的基本情况(第一个子句)也不应该是一个未实例化的变量(这就是输出中|_G488的结果。

您必须迭代第一个列表,过滤第二个列表中找到的元素,但不删除第二个列表中的元素。

例如:

filter([], _, []).
filter([Item|L1], L2, L3):-
  (member(Item, L2) -> L4=L3;L3=[Item|L4]),
  filter(L1, L2, L4).

第一个clase是递归的基本情况。它声明空列表的输出将是一个空列表。 第二个子句检查是否在第二个列表中找到输入列表的第一项。如果找到它,那么它将不会被添加到结果列表中;否则它被添加。然后它以输入列表的其余部分递归调用自身。 但绝不会从第二个列表中删除元素。

答案 1 :(得分:-1)

嗯,懒惰的方式是使用内置版findall/3member/2

filter( Xs , Ys , Rs ) :-
  findall( X , ( member(X,Xs), \+ member(X,Ys) ) , Rs ) .

表示查找所有XX是列表XsXs is *not* a member of the list Ys`的成员。

假设您的教师希望您提出自己的实现,您可能首先想要分解您的问题。你需要做两件事:

  • 迭代列表,删除在另一个列表中找到的项目。

  • 给定一个项目,确定它是否包含在另一个列表中。

这两个都很简单。要确定某个项目是否包含在列表中,您可以说:

contained_in( X , [X|Ys] ) :- % if we find the item in the list,
  ! .                         % - we succeed and eliminate any alternatives.
contained_in( X , [_|Ys] ) :- % otherwise, we discard the head of the list,
  contained_in(X,Ys) .        % - and keep looking by recursing down.

实际过滤也非常简单:

filter( []     , _  , []    ) .   % once the source list is exhausted, we're done.
filter( [X|Xs] , Ys , [X|R] ) :-  % otherwise...
  \+ contained_in(X,Ys) ,         % - if the current list item is not contained in the list of items to be removed,
  ! ,                             % - cut off alternatives,
  filter( Xs , Ys , R ) .         % - add the current item to the result list and recurse down.
  .                               % 
filter( [_|Xs] , Ys , R ) :-      % if the current list item IS contained in the list of items to be removed,
  filter(Xs , Ys , R )            % - discard it and recurse down.
  .                               % Easy!

答案 2 :(得分:-1)

您的filter只有subtract可用于许多Prolog系统(我已经使用B-Prolog,SWI-Prolog和ECLiPSe测试过):

?- subtract( [[1,2,3],[1]] , [[1]] , X ).
X = [[1, 2, 3]].

?- subtract( [[1,2,3],[1],[2,3,4],[2]] , [[1],[2]] , X ).
X = [[1, 2, 3], [2, 3, 4]].

您可以查看SWI-Prolog或ECLiPSe的来源了解实施细节。