从prolog列表中查找子列表中的元素

时间:2013-10-09 23:30:48

标签: prolog

我有这个

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

我想找到列表中的哪个子列表与数字1相同。 删除后排名第一的子列表。

会是这样的:

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

我知道这是错的,但我想解释你想做什么。

我希望我的最终名单是:

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

2 个答案:

答案 0 :(得分: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,并删除包含给定Element的所有子列表Ls。通常,要检查元素X是否在某个列表List中,我们可以使用member(X, List)。 所以我们想要一个列表列表,SubListsWithout,其中包含member(Element, SubList)为假的所有List的ListOfLists。

这是一个谓词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之外。!用于修剪搜索路径,因为一旦我们知道了一个元素是L的成员,我们不想再与L有任何关系。)

如果将L添加到SubListsWithout,则第三个子句为true,而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).

和prolog将回复,

Filtered = initial_state(0, [], [[2, 3], [2, 3]]).

答案 1 :(得分:1)

我认为你选择了正确的内置(删除/ 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在之后存储更新的初始状态(有断言,但我怀疑会纠正错误)。

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

C=[[X,_]|_]

使用_(即匿名var)是必需的,因为允许指定我们在使用它时必须忽略的复杂结构的哪个部分。我们还必须使用它来表示删除/ 3 要匹配的

delete(C,[X,_],Newlist)