编辑:在评论中纳入 CapelliC 对 delete/3 和 OP 的进一步查询的新答案。
谓词:
initial_state_without_elements(initialstate(A,B,List), Element,
initialstate(A,B,FilteredList) ):-
delete(List, Element, FilteredList).
询问:
?- initial_state_without_elements(initialstate(0,[],[[1,0],[2,3],[1,2],[2,3]]), [2,_], NewState).
NewState = initialstate(0, [], [[1, 0], [1, 2]]).
我们想要获取一些列表列表 ListOfLists,并删除所有包含给定元素的子列表 Ls。通常,要检查元素 X 是否在某个列表 List 中,我们可以使用member(X, List)
. 所以我们想要一个列表的列表,SubListsWithout,它包含所有 ListOfLists 的 Ls 为member(Element, SubList)
假。
这是一个 predicate sublists_without_elements/3
,它接受一个列表列表、一个元素和一个变量作为参数,并将变量与第一个不包含该元素的子列表的列表统一起来。这个谓词使用标准递归技术来描述列表:
sublists_without_element([], _, []).
sublists_without_element([L|Ls], Element, SubListsWithout) :-
member(Element, L), !,
sublists_without_element(Ls, Element, SubListsWithout).
sublists_without_element([L|Ls], Element, [L|SubListsWithout]) :-
sublists_without_element(Ls, Element, SubListsWithout).
第一个子句是我们的基本情况:空列表没有子列表,无论元素如何。
如果 (1) Element 是 L 的成员,并且 (2) SubListsWithout 是 Ls 的不包含 Element 的子列表的列表,则第二个子句为真。(注意: *L 并没有在这个子句中添加到 SubListsWithout 中,这意味着它已经从我们正在累积的 lits 中排除了。这里!
用于修剪搜索路径,因为一旦我们知道一个 Element 是 L 的成员,我们不想再和L有任何关系。)
如果将 L 添加到 SubListsWithout,则第三个子句为真,并且 SubListsWithout 包含 Ls 的其余子列表,这些子列表没有 Element 作为成员。
以上是编写自己的谓词来过滤列表的一种方法。能够编写和阅读这种形式的谓词很重要,因为您会看到大量的谓词。但是,您还需要了解 Prolog 实现的标准库。在 SWI-Prolg 中,您可以简单地使用exclude\3
来完成上述任务。因此,您可以通过以下方式实现您想要的目标:
filter_initial_state(initial_state(A,B,List),
Element,
initial_state(A,B,FilteredList)) :-
exclude(member(Element), List, FilteredList).
你可以这样使用它,
?- filter_initial_state(initial_state(0,[],[[1,0],[2,3],[1,2],[2,3]]), 1, Filtered).
序言会回复,
Filtered = initial_state(0, [], [[2, 3], [2, 3]]).