成员(扩展)谓词-在列表列表(任何级别)中查找元素

时间:2019-01-14 16:47:05

标签: prolog

我们都知道成员的经典Prolog谓词:

member(X, [X|T]).
member(X, [Y|T]) :- member(X,Y).

我正在努力提出扩展成员谓词,我在列表(列表等)中搜索元素。例如:

member(4, [1,2,[3,4,[5]],[6,7,9]]).
TRUE

1 个答案:

答案 0 :(得分:3)

我们可以通过三个规则来定义这样的谓词。 X是列表L的成员,而L是具有以下内容的非空列表:

  1. X是它的第一个元素;
  2. X是其第一个元素的成员(因此也是一个列表);或
  3. X是列表其余部分(其“ tail ”)的成员。

有了这三个条件,我们可以编写谓词rmember/2递归成员),例如:

rmember(X, [X|_]).    %% (1)
rmember(X, [H|_]) :-  %% (2)
    rmember(X, H).
rmember(X, [_|T]) :-  %% (3)
    rmember(X, T).

第一个条件和第三个条件在简单的member/2谓词中也存在,只有第二个条件对于递归成员检查是“唯一的”。

通过使谓词具有三个参数,我们可以略微提高上述效率,其中列表的尾部是第一个,搜索第二个元素,而列表的头是第三个。这是一种流行的方法,例如SWI-Prolog's member/2 implementation [swi-doc]

这样做的好处是我们避免多次拆箱。我们还可以限制第二种情况的模式,以便仅针对非空子列表调用此模式:

rmember_(_, El, El).
rmember_(_, El, [H|T]) :-
    rmember_(T, El, H).
rmember_([H|T], El, _) :-
    rmember_(T, El, H).

然后我们可以根据rmember/2来定义_rmember/3

rmember(X, [H|T]) :-
    rmember_(T, X, H).