Prolog的新手,对Prolog中的递归不太了解,因此我不确定如何从已经考虑的列表中删除元素。
这是我上一个问题的后续问题: Prolog: How do you iterate between two lists (nest for-loop)?
我有两个列表:
stringList([hello, hi], [bye,later], X).
函数stringList如下所示:
stringList(As, Bs, [A,B]) :-
member(A, As),
member(B, Bs).
这将产生输出:
X = [hi, bye] ;
X = [hi, later] ;
X = [hello, bye] ;
X = [hello, later].
现在,我要从两个列表中删除子列表。例如,如果X = [hi, later]
,我想打个招呼,然后下一个X = [hello, bye]
。当我的清单很大时,这一点变得更加重要。
我知道我需要递归,所以我创建了基本案例:
stringList([],[],[]).
答案 0 :(得分:1)
一种方法是使用findall/3
和delete/3
谓词。当前,您的stringList/3
一次生成一个解决方案,因此您需要使用findall/3
将所有这些解决方案收集到一个列表中,然后删除所需的任何内容:
deleteSublist(As, Bs, Elem, L):-
findall([X,Y], stringList(As, Bs, [X,Y]), L1),
delete(L1, Elem, L).
示例:
?- deleteSublist([hello, hi], [bye,later], [hi,_], L).
L = [[hello, bye], [hello, later]].
在上面的示例中,您要删除的元素可能只是[hi,bye]
,但是我们使用[hi,_]
删除所有出现的hi。
现在要回答您的问题,可以使用递归轻松完成,但是要使用递归,您需要将所有解决方案都放在一个列表中,以便稍后您可以从该列表中递归提取元素。上述解决方案中的递归部分隐藏在delete/3
内置的内部。因此,如果您想使用自己的递归解决方案,只需编写自己的delete/3
递归定义即可(我认为必须在堆栈溢出中询问该定义,以便您可以搜索或搜索它……)
另一件事,如果您希望您的解决方案一次像stringList/3
谓词中那样生成一个解决方案,那么您也可以在下面使用这种简单方法:
?- stringList([hello, hi], [bye,later], X),(X \= [hi,_]).
X = [hello, bye] ;
X = [hello, later] ;
false.
在上面的方法中,我们利用了\=
在比较[hi,bye] \= [hi,_]
时失败的优点,而如果您使用纯dif/2
则将成功:
?- stringList([hello, hi], [bye,later], X),dif(X,[hi,_]).
X = [hello, bye] ;
X = [hello, later] ;
X = [hi, bye] ;
X = [hi, later].
因此,使用dif / 2时,您将需要更详细的限制:
?- stringList([hello, hi], [bye,later], X),dif(X,[hi,bye]), dif(X,[hi,later]).
X = [hello, bye] ;
X = [hello, later] ;
false.