#prolog
Вопрос:
removeDup([],[]).
removeDup([H|T],T1) :- member(H,T), removeDup(T,T1).
removeDup([H|T],T1) :- not(member(H,T)), removeDup(T,Q), append(T1,[H],Q).
Это удаляет дубликаты, но изменяет порядок. Для добавления я ожидаю, что H будет добавлен в конец T1, а затем установлен как Q.
Как я могу сохранить заказ?
Предполагаемое поведение:
?- removeDup([1,2,3,2,4,5],X).
X = [1,2,3,4,5]
Комментарии:
1. что-то не так с вашим третьим пунктом. Вы уверены, что используете именно эту программу?
Ответ №1:
rmdup(Xs, Ys) :- rmdup1(Xs, Ys, []).
Вот Zs
накопитель для не дублирующихся элементов списка. Если X
есть Zs
, проигнорируйте его, иначе внесите в список.
rmdup1([], Ys, Zs) :- reverse(Ys, Zs).
rmdup1([X|Xs], Ys, Zs) :-
member(X, Zs) -> rmdup1(Xs, Ys, Zs);
rmdup1(Xs, Ys, [X|Zs]).
Комментарии:
1. Попробуйте
listing(rmdup1)
увидеть лучший стиль отступа для if-then-else
Ответ №2:
Я бы сделал что-то подобное:
dedupe( Xs, Set ) :- dedupe_1(Xs, [], Set).
dedupe_1( [] , _ , [] ).
dedupe_1( [X|Xs] , Seen , Set ) :-
( member(X, Seen)
-> Set1 = Set
; [X|Set1] = Set
),
dedupe_1( Xs, [X|Seen], Set1 ).
Недостатком является то, что это обходится вам дорого с точки зрения используемого пространства. Вы можете избежать этого за счет a reverse/2
в конце:
dedupe(Xs, Set) :- dedupe_1(Xs, [], Set).
dedupe_1( [] , Seen , Set ) :- reverse( Seen, Set).
dedupe_1( [X|Xs] , Seen , Set ) :-
( member(X,Seen)
-> Acc1 = Acc
; [X|Acc1] = Acc
),
dedupe_1( Xs, Acc1, Set).