Prolog: Filtering a List?

I am currently working on a very short Prolog project and just got stuck trying to apply the β€œfilter” that I created on the list. I have what you might call a filter ready, but I can't apply it. It would be better to illustrate:

filter(A, B) 

... displays "true" if certain conditions are met.

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

... displays a list containing all the elements from the second argument that make the output filter false . (Thus, if the filter (A, X) is true, the output is [Y, Z]).

I have a filter function, but now I need to apply it to the list, as shown in the second example, with the exception of all elements for which the filter returns true when applied with the first argument.

So, if the filter is simple A == B, the function should get A [A, B, A, C, D, A] and output [B, C, D], removing all the elements for which the filter is applied, obviously.

I am having problems with the basic structure of a function, so if someone can provide a basic plan for a function like this, it will be very helpful. I simplified the situation as much as possible, so I can take everything that you can provide and change for my needs.

Thanks in advance!

+16
list filter prolog meta-predicate
Nov 18 '08 at 6:24
source share
6 answers

If you are looking for higher-order functions in the Prolog, you should definitely refer to Naish (1995) , a very good source on this subject.

Its definition of filter/3 follows (it uses the notation of a list of differences, therefore avoids the need to define filter/4 ):

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

If you have questions about this predicate, please ask me in the comments. Reading paper is also highly recommended; it also challenges map , foldr and compose ! It should be noted that many of the restrictions that he mentions (such as, for example, there is no call/3 or higher order, apply not applied anymore. SWI-Prolog has =.. operator that addresses all its problems and makes arbitrary N-Logic ordering is possible.

+12
Nov 18 '08 at 18:21
source share

SWI-Prolog offers exclude/3 and other similar meta predicates. Your original problem can be encoded as follows:

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

Usage example:

 ?- filterList(A, [A, B, A, C, D, A], Out). Out = [B, C, D]. 
+9
Dec 03 '08 at 21:28
source share

There is an inherent problem with filter functions that use the success or failure of a predicate as a filter criterion: the resulting program is no longer a pure monotonous program. Therefore, he loses all his declarative properties; the only meaning that remains is a procedural phased interpretation. Here is a clean, reworked version of filtering using 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). 

Thus, the first argument is the closure / continuation, which will receive two more arguments: The element and the resulting truth value.

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

Now the results remain accurate:

 | ?- 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 

There are four possibilities by which you can filter a list of two elements by the criterion equal to X Each element may be equal or may differ.

The disadvantage of this approach is that you need to provide updated versions of all the criteria.

+3
Feb 26 '14 at 21:02
source share

Good thing you know, I just figured it out. So here I am posting the answer to my question, as expected, a really short function did the job:

 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. ). 
0
Nov 18 '08 at 6:54
source share

I get adults in the country // 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) 

This is a filter in the prolog // Asi es un filter en prolog

0
Sep 28 '17 at 18:20
source share
 filter(_,[],[]). filter(Predicate,[First|Rest],[First|Tail]) :- filter(Predicate,Rest,Tail). filter(Predicate,[_|Rest],Result) :- filter(Predicate,Rest,Result). 
0
Jan 31 '19 at 23:12
source share



All Articles