问题
The original problem was to come up with a way to get the following
remove([a,a,a,b,q,q,q,q,e,e,e]),X)
X = [a,b,q,e]
回答1:
We can solve this problem by one iteration along the list. At any point in the list we check the current element and the next element, if they are the same then we ignore the current element, else if they are different we take the current element.
rm_dup([], []).
rm_dup([X], [X]).
rm_dup([X1, X2 | Xs], [X1 | Ys]) :-
dif(X1, X2), rm_dup([X2|Xs], Ys).
rm_dup([X, X | Xs], Ys) :-
rm_dup([X | Xs], Ys).
The first and second clauses are base clauses in which there are no duplicate elements. The third and fourth clauses are recursive rules.
In third clause we state that if the input list has two values X1
and X2
and they are different dif(X1, X2)
, then keep the current value.
In fourth clause if we have same consecutive values then we ignore the current value.
The third and fourth clauses are mutually exclusive and hence to make the predicate deterministic it is better to combine them as follows
rm_dup([X], [X]) :- !.
rm_dup([X1, X2 | Xs], Ys) :-
dif(X1, X2) -> (rm_dup([X2 | Xs], Ys1), Ys = [X1 | Ys1]);
rm_dup([X2 | Xs], Ys).
Even better is to just use equality as a condition and flip the then and else clauses.
rm_dup([X], [X]) :- !.
rm_dup([X1, X2 | Xs], Ys) :-
X1 = X2 -> rm_dup([X2 | Xs], Ys);
rm_dup([X2 | Xs], Ys1), Ys = [X1 | Ys1].
回答2:
Kinda long, but this solved it.
delete(_,[],[]).
delete(X,[X|T],R):- delete(X,T,R).
delete(X,[H|T],[H|R]) :- delete(X,T,R).
remove([],[]).
remove([H|T], [H|R]) :-
member(H,T),!,
delete(H,T,R1),
remove(R1,R).
remove([H|T],[H|R]):-
remove(T,R).
回答3:
You can simply use sort.
First: In the base class if the List are empty stop.
Second: In the second predicate, take the list and sort it. Display the answer in K.
remove_extras([],[]).
remove_extras([H|T],K):-
sort([H|T], K).
?-remove_extras([a,a,a,b,q,q,q,q,e,e,e],X).
X = [a, b, e, q]
?-remove_extras([1,3,2,5,1,6,1,2,7],X).
X = [1, 2, 3, 5, 6, 7]
If you don't want to use sort, you can use the following predicates: Remove duplicates checks for elements existing more than once and keeps them in the list.
First: The base case says that if the lists are empty stop.
Second: The second predicate checks if an element exist in the remaining list (member) then don't add it to the final list.
Third: The third predicate says, if the element is in not the remaining list then add it to the final list.
remove_duplicates([],[]).
remove_duplicates([H | T], List) :-
member(H, T),
remove_duplicates( T, List).
remove_duplicates([H | T], [H|T1]) :-
\+ member(H, T),
remove_duplicates( T, T1).
来源:https://stackoverflow.com/questions/65046171/eliminate-consecutive-duplicates-of-list-elements-with-prolog