18

我目前正在做一个关于 Prolog 的非常短的项目,只是在尝试将我创建的“过滤器”应用于列表时遇到了困难。我已经准备好你可以称之为过滤器的东西,但我无法应用它。如果我说明一下会更好:

filter(A, B) 

...如果满足某些条件,则输出“真”。

filterList(A, [X, Y, Z])

...输出一个列表,其中包含第二个参数中使过滤器输出为false的所有元素。(因此,如果 filter(A, X) 为真,则输出为 [Y, Z] )。

我已经准备好“过滤器”函数,但现在我需要将它应用到列表中,如第二个示例所示,不包括使用第一个参数应用时过滤器返回 true 的所有元素。

因此,如果过滤器是简单的 A == B,则该函数应该接收 A [A,B,A,C,D,A] 并输出 [B,C,D],并删除所有显然,过滤器适用。

我在函数的基本结构上遇到了麻烦,所以如果有人可以为这样的函数提供一个基本的大纲,那将会有很大的帮助。我已经尽可能地简化了我的情况,所以我可以接受你可以提供的任何东西,并根据我的需要进行修改。

提前致谢!

4

6 回答 6

13

SWI-Prolog 提供exclude/3和其他此类元谓词。您的原始问题可以这样编码:

are_identical(X, Y) :-
    X == Y.

filterList(A, In, Out) :-
    exclude(are_identical(A), In, Out).

使用示例:

?- filterList(A, [A, B, A, C, D, A], Out).
Out = [B, C, D].
于 2008-12-03T21:28:06.753 回答
10

如果您在 Prolog 中搜索高阶函数,您应该明确参考Naish (1995),这是一个非常好的资源。

他的定义filter/3如下(他使用差异列表符号,因此不必定义filter/4):


filter(_,[],[]).
filter(P, A0-As0, As) :-
    (
        call(P, A0) -> As = A0-As1
    ;
        As = As1
    )
    , filter(P, As0, As1).

我对这个谓词有疑问,请在评论中问我。强烈推荐阅读这篇论文,它还定义了map,foldrcompose! 请注意,他提到的许多限制(例如,缺失call/3或高阶apply不再适用。SWI-Prolog 具有=..运算符,它解决了他的所有问题并使任意 n 阶逻辑成为可能。

于 2008-11-18T18:21:58.647 回答
4

将谓词的成功或失败作为过滤标准的过滤函数存在一个固有问题:生成的程序不再是纯单调程序。因此,它失去了所有的声明性属性——唯一剩下的含义是程序上的逐步解释。这是一个纯粹的、具体化的过滤版本,使用if_/3

tfilter(_CT_2,    [], []).
tfilter(CT_2, [E|Es], Fs0) :-
   if_(call(CT_2,E), Fs0 = [E|Fs], Fs0 = Fs ),
   tfilter(CT_2, Es, Fs).

因此,第一个参数是一个闭包/延续,它将接收两个进一步的参数:元素和结果真值。

=(X,X,true).
=(X,Y,false) :- dif(X,Y).

现在,结果仍然准确:

| ?- tfilter(=(X),[A,B],Xs).
B = A,
X = A,
Xs = [A,A] ? ;
X = A,
Xs = [A],
dif(A,B) ? ;
X = B,
Xs = [B],
dif(B,A) ? ;
Xs = [],
dif(X,A),
dif(X,B) ? ;
no

有四种可能性如何通过等于 的标准过滤两个元素的列表X。每个元素可能相同也可能不同。

这种方法的缺点是必须提供所有标准的具体版本。

于 2014-02-26T21:02:42.620 回答
0

好吧,你知道我刚刚想通了。所以,这是我提交我自己问题的答案,正如预期的那样,一个非常短的函数完成了这项工作:

filterList(_,[],R,R).           % Returns answer when the list is exhausted.
filterList(L,[A|List],Temp,Res) :-
   filterList(L,List,New,Res),  % Recursive call, New is either the same list
   (  filter(L,A),              % in case the filter outputs true, or the list
      New = Temp
   ;  New = [A|Temp]            % plus the current element otherwise.
   ).
于 2008-11-18T06:54:06.350 回答
0

我得到了一个国家的成年人 // Obtengo los adultos de un pais, Country = Pais, People = Personas, Person = una sola Persona

habitants(USA, [juan, pedro, david])

adults(Adults, Country) :-
     findall(Person, (habitants(Country,People), member(People, Person), adult(Person)), Adults)

这是序言中的过滤器 // Asi es un filter en prolog

于 2017-09-28T18:20:34.943 回答
0
filter(_,[],[]).
filter(Predicate,[First|Rest],[First|Tail]) :-
   filter(Predicate,Rest,Tail).
filter(Predicate,[_|Rest],Result) :-
   filter(Predicate,Rest,Result).
于 2019-01-31T23:12:29.303 回答