list - Prolog:如何从列表中删除子列表?(后续问题)
问题描述
Prolog 的新手,不太了解 Prolog 中的递归,所以我不确定如何取出已经考虑过的列表中的元素。
这是我上一个问题的后续问题: Prolog:您如何在两个列表之间进行迭代(嵌套 for 循环)?
我有两个清单:
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([],[],[]).
解决方案
一种方法是使用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.
推荐阅读
- android - setOnItemListener 不打开布局
- erlang - 无法在 Erlang 中生成进程
- windows - 如何让 Cmake 在 Windows 中找到 tesseract 库(Findtesseract.cmake)?
- android - 为什么我无法使用 google 帐户登录 android studio?
- python - 文件未在目录中列出,但可以使用 Python / Pandas 从那里写入和加载。环境问题?
- reactjs - 如何解决问题:TypeError: self.env.emit is not a function?
- git - 将 HEAD 推送到远程分支,无需本地分支
- excel - 运行时错误 '1004' 应用程序定义或对象定义错误'
- java - 在 Java 的驱动程序类中找不到参数
- mongodb - MongoDB 不区分大小写的索引不起作用