2008-11-18 59 views
15

Actualmente estoy trabajando en un proyecto muy corto en Prolog, y me atasqué 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 lo ilustrara:Prólogo: ¿Filtrar una lista?

filter(A, B) 

... resultados 'verdaderos' si se cumplen ciertas condiciones.

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

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

Tengo la función "filtro" lista, pero ahora necesito aplicarla a una lista como se muestra en el segundo ejemplo, excluyendo todos los elementos para los que 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 todo los elementos para los cuales se aplica el filtro, 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 de antemano!

Respuesta

11

Si usted está buscando para las funciones de orden superior en Prolog, que sin duda debe consultar Naish (1995), una muy buena recurso en esto.

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


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

que tiene alguna pregunta sobre este predicado, me pueden solicitar en el comentario . La lectura del papel también es muy recomendable, también es map, foldr y compose. Tenga en cuenta que muchas de las limitaciones que menciona (como, por ejemplo, call/3 faltante o apply de orden superior ya no se aplican. SWI-Prolog tiene el operador =.., que soluciona todas sus dudas y hace posible una lógica de orden n arbitraria.

+1

Pitty Naish propone aplicar/3 en sus conclusiones, pero supongo que el camino actual es usar call/n. apply/3 es simplemente call/3. –

+2

Consulte para una discusión por qué se disputa la referencia de Naish: http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/naish.html –

0

Bueno, ¿qué sabías? Lo acabo de descubrir. Por lo tanto, aquí está mi presentar una respuesta a mi propia pregunta, como se esperaba una función muy corto 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. 
    ). 
+1

Esta versión siempre tiene éxito para cualquier lista. ¿Destinado a? – false

7

SWI-Prolog ofrece exclude/3 y otros meta-predicados Su problema original puede ser codificada como esto:. ejemplo

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

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

Uso:

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

include (<(5), [3,4,5,6 , 7], As). funciona igual que filter (<(5), [3,4,5,6,7], As). excluir es el inverso porque da los mismos resultados que filter (> = (5), [3,4,5,6,7], As). – joeblog

3

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.He aquí una versión pura, 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, pues, un cierre/continuación que recibirá otros dos argumentos: El elemento y el valor de verdad resultante.

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

Ahora, los resultados siguen siendo preciso:

| ?- 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 pueden 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 hay que proporcionar versiones reificadas de todos los criterios.

0

puedo obtener los adultos de un país // Obtengo los Adultos de Pais de la ONU, 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) 

Se trata de un filtro en el prólogo // Asi es un filter en prolog

Cuestiones relacionadas