Prolog: How do I delete a sublist from a list? (Fo

2019-08-27 00:09发布

问题:

New to Prolog and don't understand recursion in Prolog very well so I am not sure how to take out an element in a list that has already been considered.

This is a follow-up question to my previous question: Prolog: How do you iterate between two lists (nest for-loop)?

I have two lists:

stringList([hello, hi], [bye,later], X).

where the function stringList looks like:

stringList(As, Bs, [A,B]) :-
  member(A, As),
  member(B, Bs).

This produces the output:

X = [hi, bye] ;
X = [hi, later] ;
X = [hello, bye] ;
X = [hello, later].

Now I want delete the sublist from the two lists. For example if X = [hi, later], I want to take out hi and later so my next X = [hello, bye]. This becomes more important when my list is big.

I know I need to recurse so I created the base case:

stringList([],[],[]).

回答1:

One way would be to use findall/3 and delete/3 predicates. Currently your stringList/3 generates solutions one at a time, so you need to gather all this solutions in one list using findall/3 and then delete whatever you want:

deleteSublist(As, Bs, Elem, L):- 
       findall([X,Y], stringList(As, Bs, [X,Y]), L1),
       delete(L1, Elem, L).

Example:

?- deleteSublist([hello, hi], [bye,later], [hi,_], L).
L = [[hello, bye], [hello, later]].

In the above example the element you want to delete could be just [hi,bye] but we use [hi,_] to delete all occurrences of hi.

Now to answer your question this could be easily done with recursion but in order to use recursion you need all the solution in one list so that later you can recursively extract elements from that list. The part of recursion in the above solution is hidden inside built in delete/3. So if you want to use your own recursive solution just write your own recursive definition of delete/3 (I think this must be already asked in stack overflow so you might search it or google it...)

Another thing, if you want your solution to generates one solution at a time like in stringList/3 predicate you could also use this simple way below:

?- stringList([hello, hi], [bye,later], X),(X \= [hi,_]).
X = [hello, bye] ;
X = [hello, later] ;
false.

In the above we take the advantage that \= fails when e.g comparing [hi,bye] \= [hi,_] while if you used the pure dif/2 this would succeed:

?- stringList([hello, hi], [bye,later], X),dif(X,[hi,_]).
X = [hello, bye] ;
X = [hello, later] ;
X = [hi, bye] ;
X = [hi, later].

So using dif/2 you would need more detailed restriction:

?- stringList([hello, hi], [bye,later], X),dif(X,[hi,bye]), dif(X,[hi,later]).
X = [hello, bye] ;
X = [hello, later] ;
false.


标签: list prolog