2016-04-28 8 views
1

Ich habe zwei Listen L1 und L2:findAll/3 für eine sublist bestimmte Kriterien erfüllt,

L1=[1,4,5,6,7,8]. 
L2=[2,3]. 

Und ein Prädikat:

related(X,Y). 

Ich möchte L3 eine Liste zu finden:

  1. was ist eine Unterliste von L1

  2. , bei dem alle Elemente von L3 sind Lösungen für Y, wo alle Werte von L2 sind Lösungen für X

Mit anderen Worten, alle Werte von L2 in X speisen und finden heraus, welche der Werte von L1 werden entsprechende Lösungen für Y sein.

+2

Ihr Titel sagt, was zu verwenden ist ('findall/3') beschreiben Sie einfach Ihre Bedingung im zweiten Argument. Sie möchten alle 'X' finden, zum Beispiel,' member (X, L1) '(Ihre erste Bedingung), dann haben Sie eine konjunktive Bedingung, (b), einzuschließen. Sie können einen zusammengesetzten Ausdruck in 'findall/3' haben:' findall (X, (member (X, L1), ..., ...), L3) .' – lurker

Antwort

2

findall/3 Mit diesem kann auf diese Weise durchgeführt werden (wenn ich Ihre Bedingungen richtig zu verstehen):

findall(Y, (member(Y, L1), member(X, L2), related(X, Y)), L3). 

In meinem Kommentar, ich hatte die X um ein bisschen gemischt durch Ihre Bedingungen Verlesen, aber die Idee ist immer noch das gleiche. Sie müssen nur das richtige Ziel als zweites Argument für findall/3 einrichten, um das gewünschte Ergebnis zu erhalten.


Wenn Sie einzigartige wollen, bestellte Ergebnisse können Sie setof/3 verwenden:

setof(Y, (member(Y, L1), member(X, L2), related(X, Y)), L3). 
+0

Das einzige Problem, an das ich denken kann, ist, dass man es sollte Verwenden Sie 'once' für das' member (X, L2), verwandte (X, Y) ', da nur eins existieren soll. Schöne Antwort übrigens. +1. –

+0

@WillemVanOnsem danke !, und ja, guter Fang. Ich würde wahrscheinlich 'setof/3' in diesem Fall verwenden. Mit "once/1" müsste man vorsichtig sein, um gültige, einzigartige Lösungen nicht zu beschneiden. Es ist nicht klar, was das Verhalten von "verwandt/2" ist. – lurker

+0

Satz von ist immer noch nicht ganz gleichwertig, denke ich. Das Ergebnis sollte eine Unterliste sein. Die ursprüngliche Liste kann Duplikate enthalten, die vielleicht im Ergebnis dupliziert werden sollten. Trotzdem ist die Frage etwas unterspezifiziert. –

1

findall/3 ist wie:

findall(+Template, :Goal, -Bag) 

wo:

  • Bag die Liste der Ergebnisse ist, dass Sie möchte erhalten;
  • Goal ist das Prädikat (oder die Kombination von Prädikaten), das erfolgreich sein sollte; und
  • Template ist ein Ausdruck, der das Format der Ergebnisse beschreibt.

Nun wollen wir dieses Prädikat verwenden, um etwas Konstruieren zu tun:

  1. , die eine Unterliste von L1

Sie suchen alle Elemente Y in L1 ist, so ist die Vorlage eindeutig X1 und das Ziel wird bei l Osten enthält member(X,L1).So, jetzt oder findall/3 ist so geformt, wie:

findall(Y,(member(Y,L1),...),L3) 
  1. , bei dem alle Elemente von L3 sind Lösungen für Y, wo alle Werte von L2 sind Lösungen für X

Da es mindestens eine X in L2 sein sollte, so dass related(X,Y) hält. Es bedeutet, dass wir ein once/1 erzwingen verwenden, der von dem Augenblick, wo man X gefunden wird, unser Anruf beendet (und keine Wiederholungen von Y auftreten), so daß X ein Elemente (member/2) von L2 und related/2 halten. ... ist also gleich:

once((member(X,L2),rel(X,Y))) 

Oder jetzt die Vollversion:

findall(Y,(member(Y,L1),once((member(X,L2),rel(X,Y)))),L3) 

Beispiel:

zum Beispiel Gegeben:

rel(2,1). 
rel(3,1). 
rel(2,4). 
rel(3,7). 

Das Ergebnis ist:

?- L1=[1,4,5,6,7,8],L2=[2,3],findall(Y,(member(Y,L1),once((member(X,L2),rel(X,Y)))),L3). 
L1 = [1, 4, 5, 6, 7, 8], 
L2 = [2, 3], 
L3 = [1, 4, 7]. 

So wird 1 nur einmal vorkommen, während es zwei X s für Y=1 gibt, für die die Bedingung gilt.

Verwandte Themen