简体   繁体   中英

Prolog Remove element from list

I have the following fact to remove all occurences of a element in a list. Although the output is correct, the element is just replaced for a blank space

remover( _, [], []).
remover( R, [R|T], [T2]) :- remover( R, T, T2).
remover( R, [H|T], [H|T2]) :- H \= R, remover( R, T, T2).

When I call remover the output is:

remover(3,[1,2,3,4,3],Res)
Res = [1, 2, [4, []]]

I also have the following fact to remove only the first occurence but the output is the same from above

remover_primeira( _, [], []).
remover_primeira( R, [R|T], [T2]) :-remover_primeira( R, T, T2),!.
remover_primeira( R, [H|T], [H|T2]) :- H \= R, remover_primeira( R, T, T2).

What am I doing wrong?

You should not wrap T2 in a singleton list in the second clause, it should be:

remover( _, [], []).
remover( R, [R|T], ) :- remover( R, T, T2).
remover( R, [H|T], [H|T2]) :- H \= R, remover( R, T, T2).

In case you only need to remove the first occurrence, then you should not recurse from the moment you found that element:

remover( _, [], []).
remover( R, [R|T], ).
remover( R, [H|T], [H|T2]) :- H \= R, remover( R, T, T2).

The solution by @WillemVanOnsem, derived from the OP code, uses term unification when comparing the element to be removed with the elements of the list (an alternative would be to use term equality ). The solution works for ground terms. But can result in unexpected results when the terms are not ground. For example:

| ?- remover(a(_), [a(1), b(2), a(3), b(4)], List).

List = [b(2),a(3),b(4)] ? ;
no

Consider the following alternative definition of the remover/3 predicate:

remover(_, [], []).
remover(R, [H|T], T2) :- \+ H \= R, remover(R, T, T2).
remover(R, [H|T], [H|T2]) :- H \= R, remover(R, T, T2).

With this solution, the query above gives:

| ?- remover(a(_), [a(1), b(2), a(3), b(4)], List).         

List = [b(2),b(4)] ? ;
no

Be sure to have a clear understanding of the semantics you want for the predicate.

You can also solve it like this:

del(E1,[E1|T1],L2) :- T1 == L2, !. %base case
del(E1,[H1|T1],[H2|T2]) :- H1 == H2, del(E1,T1,T2). %general case

I'm not sure if there's an optimization to be done, because I did it in a couple of minutes, but it works quite nicely.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM