1

我有这个

initialstate(0,[],[[1,0],[2,3],[1,2],[2,3]]).

我想找出列表中的哪个子列表与数字 1 相同。然后删除具有数字 1 的子列表。

它会是这样的:

?- initialstate(_,_,[X,_]), initialstate(_,_,list),
 delete(list,X,Newlist),assertz(initialstate(A,B,Newlist)).

我知道这是错误的,但我想向您解释我想要做什么。

我希望我的最终名单是:

initialstate(0,[],[[2,3],[2,3]]).
4

2 回答 2

1

我认为您选择了正确的内置函数(delete/3),但有些细节有误。这是一个有效的“查询”:

?- retract(initialstate(A,B,C)), C=[[X,_]|_], delete(C,[X,_],Newlist), assertz(initialstate(A,B,Newlist)).
A = 0,
B = [],
C = [[1, 0], [2, 3], [1, 2], [2, 3]],
X = 1,
Newlist = [[2, 3], [2, 3]].

首先:如果您在没有先进行撤消的情况下执行 assertz,那么您将以几乎重复的数据结束,并且可能不是您想要的。assertz 在旧状态之后存储更新的初始状态(有 asserta,但我怀疑会纠正错误)。

其次,注意如何使用模式匹配来提取基本信息:

C=[[X,_]|_]

_(即匿名变量)的使用是必不可少的,因为它允许指定在使用它时我们必须忽略复杂结构的哪一部分。我们还必须使用它来指示删除/3匹配什么。

delete(C,[X,_],Newlist)
于 2013-10-10T05:44:32.673 回答
1

编辑:在评论中纳入 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]]).
于 2013-10-10T05:19:44.177 回答