list filter prolog meta-predicate

Prólogo: ¿Filtrar una lista?



filter prolog (5)

Si está buscando funciones de orden superior en Prolog, debería consultar a Naish (1995) , un muy buen recurso al respecto.

Su definición de filter/3 es la siguiente (usa notación de lista de diferencias, por lo tanto, evita tener que definir filter/4 ):

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

Si tiene preguntas sobre este predicado, por favor pregúnteme en el comentario. También es muy recomendable leer el papel, ¡también puede map , foldr y compose ! Tenga en cuenta que muchas de las limitaciones que menciona (como, por ejemplo, una call/3 perdida call/3 o una apply orden superior ya no se aplican. SWI-Prolog tiene el operador =.. , que aborda todas sus inquietudes y hace n- arbitrariamente orden lógica posible.

Actualmente estoy trabajando en un proyecto muy corto en Prolog, y me quedé atascado tratando de aplicar un "filtro" que he creado a una lista. Tengo lo que podría llamar el filtro listo, pero no puedo aplicarlo. Sería mejor si ilustro:

filter(A, B)

... produce "verdadero" si se cumplen ciertas condiciones.

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

... muestra una lista que incluye todos los elementos del segundo argumento que hacen que la salida del filtro sea falsa . (Entonces, si el filtro (A, X) es verdadero, la salida es [Y, Z]).

Tengo la función de "filtro" lista, pero ahora necesito aplicarla a una lista como se muestra en el segundo ejemplo, excluyendo todos los elementos para los cuales el filtro devuelve verdadero cuando se aplica con el primer argumento.

Entonces, si el filtro es un simple A == B, se supone que la función debe recibir A [A, B, A, C, D, A] y la salida [B, C, D], habiendo eliminado todos los elementos para los cuales el filtro se aplica, obviamente.

Tengo problemas con la estructura básica de la función, por lo que si alguien pudiera proporcionar un esquema básico para una función como esta, sería de gran ayuda. He simplificado mi situación tanto como sea posible para poder tomar lo que sea que pueda proporcionar y modificarlo para mis necesidades.

¡Gracias por adelantado!


SWI-Prolog ofrece exclude/3 y otros meta-predicados. Su problema original puede codificarse así:

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

Ejemplo de uso:

?- filterList(A, [A, B, A, C, D, A], Out). Out = [B, C, D].


Bueno, ¿qué sabías? Simplemente lo descubrí. Entonces, aquí estoy yo presentando una respuesta a mi propia pregunta, como se esperaba, una función realmente corta hizo el trabajo:

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. ).


Hay un problema inherente con las funciones de filtro que toman el éxito o el fracaso de un predicado como criterio para el filtrado: El programa resultante ya no es un programa puro monotónico. Por lo tanto, pierde todas sus propiedades declarativas; el único significado que queda es una interpretación paso a paso del procedimiento. Aquí hay una versión pura y reificada de filtrado usando 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).

El primer argumento es, por lo tanto, un cierre / continuación que recibirá dos argumentos más: el elemento y el valor de verdad resultante.

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

Ahora, los resultados siguen siendo precisos:

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

Hay cuatro posibilidades de cómo una lista de dos elementos se puede filtrar por el criterio de ser igual a X Cada elemento puede ser igual o puede ser diferente.

La desventaja de este enfoque es que uno tiene que proporcionar versiones reificadas de todos los criterios.


Obtengo los adultos de un país // Obtengo los adultos de un país, País = País, Personas = Personas, Persona = una sola Persona

habitants(USA, [juan, pedro, david]) adults(Adults, Country) :- findall(Person, (habitants(Country,People), member(People, Person), adult(Person)), Adults)

Este es un filtro en prolog // Asi es un filtro en prolog