2013-09-28 54 views
4

我想从列表中删除所有包含[['One', _], _]的列表。我创建了以下条款,delete_all,永远奏效,除了我的情况:如何从列表中删除所有子列表?

delete_all(_,[],[]) :- !. 
delete_all(X,[X|Tail],List) :- 
    !, 
    delete_all(X,Tail,List). 
delete_all(X,[A|Tail],[A|List]) :- 
    delete_all(X,Tail,List). 

例子:(这个效果很好)

?- delete_all(3,[3,4,3,5,3],K). 
K = [4, 5] . 

但效果很差:

delete_all([['One', _], _], [[['One', 'Six'], 94], 
    [['One', 'Ten'], 13], [['Two', 'Nine'], 35]], Y). 
Y = [[['One', 'Ten'], 13], [['Two', 'Nine'], 35]]. 

为什么它只删除第一个元素?什么可能是错的?

+0

非常感谢你。 – Vincenzoni

回答

1

好,测试,这里是一个正在运行的:

delete_all(E, L, R) :- findall(X, (member(X, L), X \= E), R). 

我认为您的代码不工作,因为它实例 X,则抑制了delete/3还matches.The文件(即做你所追求的,只是交换参数)足够清楚地说明问题。

你应该改变你的第一句话

delete_all(X,[E|Tail],List):- 
    \+ X \= E, !, delete_all(X,Tail,List). 
1

我想问题在于,您的第一个术语(您正在搜索的模式)包含变量和那些变量以及您在扫描列表时使用列表元素的变量'unify'。一旦你传递了一个匹配的元素,模式中的变量就会被实例化为该元素中相应项的值,从而防止进一步匹配。

一个可能的解决方案是检查您的模式和您的元素是否为unifiable但最终没有统一它们。

像这样的东西可能适合您的需要:

delete_all(_,[],[]):-!. 

delete_all(X,[H|Tail],List):- 
    unifiable(X, H, _), 
    !, 
    delete_all(X,Tail,List). 

delete_all(X,[A|Tail],[A|List]):- 
    delete_all(X,Tail,List). 

如果您正在使用邑,你将不得不进口library(terms)

:- use_module(library(terms)). 

另一种解决办法是使用棘手not(not(X = H))而不是unifiable,它检查是否可以统一H和X,如果你能内不会阻止实例化,第二个返回true。

更新:正如CapelliC添加的那样,\+ X \= E等于not(not(X = E)),但具有现在更标准的语法。