2008-11-18 12 views
15

Ich arbeite gerade an einem sehr kurzen Projekt auf Prolog, und bin gerade stecken geblieben und versuche, einen "Filter", den ich erstellt habe, auf eine Liste anzuwenden. Ich habe, was man den Filter nennen könnte, aber ich kann es nicht anwenden. Es wäre besser, wenn ich folgendes illustriere:Prolog: Filtern einer Liste?

filter(A, B) 

... gibt 'true' aus, wenn bestimmte Bedingungen erfüllt sind.

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

... gibt eine Liste, die alle Elemente aus dem zweiten Argument enthält, die die Filterausgabe falschen machen. (Wenn also der Filter (A, X) wahr ist, lautet die Ausgabe [Y, Z]).

Ich habe die "Filter" -Funktion bereit, aber jetzt muss ich es auf eine Liste anwenden, wie im zweiten Beispiel gezeigt, mit Ausnahme aller Elemente, für die der Filter True zurückgibt, wenn mit dem ersten Argument angewendet.

Also, wenn der Filter ein einfaches A == B ist, soll die Funktion A [A, B, A, C, D, A] erhalten und Ausgabe [B, C, D], alle entfernt haben die Elemente, für die der Filter gilt, offensichtlich.

Ich habe Probleme mit der grundlegenden Struktur der Funktion, also wenn jemand eine grundlegende Gliederung für eine Funktion wie diese liefern könnte, wäre es eine große Hilfe. Ich habe meine Situation so weit wie möglich vereinfacht, damit ich alles, was Sie mir anbieten können, übernehmen und für meine Bedürfnisse anpassen kann.

Vielen Dank im Voraus!

Antwort

11

Wenn Sie für Funktionen höherer Ordnung in Prolog suchen, dann sollten Sie auf jeden Fall Naish (1995) konsultieren, eine sehr gute Ressource zu diesem Thema.

Seine Definition von filter/3 ist die folgende (er verwendet Unterschied Liste Notation daher filter/4 definieren entkommt mit):


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

ich Sie Fragen zu diesem Prädikat haben, mich bitte im Kommentar fragen . Lesen Sie das Papier ist auch sehr empfehlenswert, es auch map, foldr und compose! Beachten Sie, dass viele der von ihm erwähnten Einschränkungen (wie zum Beispiel eine fehlende call/3 oder eine höhere apply nicht mehr gelten. SWI-Prolog hat den Operator =.., der alle seine Anliegen anspricht und eine beliebige n-Reihenfolge-Logik ermöglicht.

+1

Pitty Naish schlägt in seinen Schlussfolgerungen apply/3 vor, aber ich denke, der aktuelle Weg ist Call/n zu verwenden. apply/3 ist einfach Call/3. –

+2

Siehe für eine Diskussion, warum Naish Referenz umstritten ist: http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/naish.html –

0

Nun, was weißt du, ich habe es gerade herausgefunden. Also mir, hier ist eine Antwort auf meine eigene Frage vorlegt, wie erwartet eine wirklich kurze Funktion hat seinen Zweck erfüllt:

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

Diese Version ist immer erfolgreich für jede Liste. Beabsichtigt? – false

7

SWI-Prolog bietet exclude/3 und andere solche Meta-Prädikate Ihre ursprüngliche Problem kann wie folgt codiert werden:.

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

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

Anwendungsbeispiel:

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

enthalten (<(5), [3,4,5,6 , 7], As). funktioniert genauso wie Filter (<(5), [3,4,5,6,7], As). Ausschließen ist das Gegenteil, dass es die gleichen Ergebnisse wie Filter (> = (5), [3,4,5,6,7], As) ergibt. – joeblog

3

Es gibt ein inhärentes Problem mit Filterfunktionen, die den Erfolg oder Misserfolg eines Prädikats als Filterkriterium nehmen: Das resultierende Programm ist kein reines monotones Programm mehr. Es verliert daher alle seine deklarativen Eigenschaften — die einzige verbleibende Bedeutung ist eine prozedurale Schritt-für-Schritt-Interpretation.Hier ist eine reine, verdinglichter Version des Filterns unter Verwendung 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). 

Das erste Argument ist somit ein Verschluss-/Fortsetzungs daß zwei weitere Argumente erhalten wird: Das Element und der resultierenden Wahrheitswert. Jetzt

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

bleiben Ergebnisse präzise:

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

Es gibt vier Möglichkeiten, wie eine Liste von zwei Elemente können durch das Kriterium der gleich X gefiltert werden. Jedes Element kann gleich oder unterschiedlich sein.

Der Nachteil dieses Ansatzes ist, dass man verdinglichte Versionen aller Kriterien zur Verfügung stellen muss.

0

bekomme ich die Erwachsenen eines Landes // Obtengo los adultos de un pais, Land = Pais, Menschen = Personas, Person = una sola Persona

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

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

Dies ist ein Filter in Prologs // Asi es un filter en prolog