したがって、指定されたリストから重複する要素を削除する述語_remove_duplicates/2
_を記述する必要があります。例えば:
?- remove_duplicates([a,a,b,c,c], List). List = [a,b,c] Yes
私はSWI-Prologを2日間しか学習しておらず、Prologの基本のみを理解していることを覚えておいてください。これは私が現在持っているものです:
remove_duplicates([H | T], List) :- member(H, T), append(T, [], List1).
これはリスト_[a,a,b,c]
_では機能しますが、テールの2つの要素が同じであるリストでは機能しません。どういうわけか私は一時的なリストにヘッドを削除し、新しいヘッドを作成し、述語を繰り返す必要があると考えました。どうすればいいのか分かりません。また、たとえば_[a,b,b,c,]
_のようなリストのように、ヘッドがテールにない場合、member(H, T)
がtrueではないため、ターミナルはFalse
とだけ表示します。
何か案は?
重複を削除するには、順序が重要ではない場合、最も簡単なのはsort/2
:
?- sort([a,a,b,b,c], X).
X = [a, b, c].
?- sort([c,c,a,a,b], X).
X = [a, b, c].
もちろん、要素の元の順序が失われていることがわかります。さらに重要なのは、これは、並べ替えるリストが既に固定されている(自由変数がない)場合にのみ正しいことを保証するだけです。この小さな例を考えてみましょう:
?- sort([X,Y], [a,a]).
X = Y, Y = a.
あなたの目標が重複を削除することである場合、正確に正しく感じていません...
だからあなたも書いたかもしれません:
must_be(ground, List), sort(List, Unique).
自分で行うこともでき、元の順序を維持できます。しかし、その場合は、これまでに見た要素を記録しておく必要があります。たとえば、追加のリストにそれらを保持できます。
これまでに見た要素のリストは最初は空です
list_unique(List, Unique) :-
list_unique_1(List, [], Us).
list_unique_1([], _, []).
list_unique_1([X|Xs], So_far, Us) :-
list_unique_2(X, Xs, So_far, Us).
これまでに見たすべての要素がXと異なる場合は、それを一意の要素のリストに入れて、これまでに見た要素のリストに追加します。
list_unique_2(X, Xs, So_far, [X|Us]) :-
maplist(dif(X), So_far),
list_unique_1(Xs, [X|So_far], Us).
これまでに要素が表示されている場合は、スキップしてください。
list_unique_2(X, Xs, So_far, Us) :-
memberchk(X, So_far),
list_unique_1(Xs, So_far, Us).
これは、最も簡単な方法です。より複雑になる可能性のある他の賢明な方法がありますが、これが最も簡単に記述できます。
述語に関するいくつかの問題があります。
remove_duplicates([H | T], List) :-
member(H, T),
append(T, [], List1).
まず、再帰的な述語が必要です。リストの先頭を確認しますが、リストの末尾を再帰的に確認しません。
したがって、次のように変更できます。
remove_duplicates([H | T], List) :-
member(H, T),
remove_duplicates( T, List).
上記は再帰的に尾を呼び出します。
次に、hがリストのメンバーでない場合にどうなるかを決定する必要があるため、別の句を追加する必要があります。
remove_duplicates([H | T], [H|T1]) :-
\+member(H, T),
remove_duplicates( T, T1).
上記は、HがTに存在するかどうかを確認し、存在しない場合は、リストの最初の要素を要素Hに強制します。
これがあまり明確でない場合、上記はこれと同じです。
remove_duplicates([H | T], List) :-
\+member(H, T),
List=[Head|Tail],
Head=H,
remove_duplicates( T, Tail).
これはあまりエレガントではありません。前の仕組みを理解するためです。
最後に、空のリストの再帰のベースが必要です。
remove_duplicates([],[]).
したがって、上記の句による述語remove_duplicatesは次のようになります。
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).
ただし、上記の例では要素ごとに1回しか保持されないことに注意する必要があります。
remove_duplicates([a,a,b,c],L).
L = [a, b, c] ;
false.
これは問題ありませんが、以下の例を確認してください。
remove_duplicates([a,a,b,a,c],L).
L = [b, a, c] ;
L = [b, a, c] ;
false.
これはL = [b、a、c]を返します。これは、リストの最初の2つの「a」を消去し、3番目のみを保持したためです。
重複のみを消去したい場合は、メンバー述語のため、上記は機能しません。あなたは書くことができます:
remove_duplicates2([],[]).
remove_duplicates2([H],[H]).
remove_duplicates2([H ,H| T], List) :-remove_duplicates( [H|T], List).
remove_duplicates2([H,Y | T], [H|T1]):- Y \= H,remove_duplicates( [Y|T], T1).
述語remove_duplicates2はremove_duplicatesに似ていますが、いくつかの重要な違いがあります:
1)メンバーを使用しませんが、2つのSAME要素を持つリスト[H、H | T]があり、1つだけを保持する場合に何が起こるかを調べます。そのため、最初のHを無視して、recursively remove_duplicates2([H | T]、L)。
2)[H、Y | T](少なくとも2つの要素H、Yとリストの末尾を含むリスト)を入力し、H\= Yの場合、remove_duplicates2([Y | T]、T1)を呼び出し、戻りたいリストにHを格納しました。
3)最後に、すべての句には少なくとも2つの要素が必要であるため、再帰のベースは1つの要素を持つリストです:remove_duplicates2([H]、[H])。
4)句remove_duplicates2([]、[])。入力が空のリストの場合にのみ使用されるため、この入力をカバーする必要があります。
Remove_duplicates2述語はあなたに与えるでしょう:
remove_duplicates2([a,a,b,a,c],L).
L = [a, b, a, c] ;
false.
remove_duplicates2([a,a,b,c],L).
L = [a, b, c] ;
false.
これを試してください、それがあなたを助けることを願っています:
delete3(_,[],[]).
delete3(X,[X|T],R):- delete3(X,T,R).
delete3(X,[H|T],[H|R]) :- delete3(X,T,R).
remove_duplicates([],[]).
remove_duplicates([H|T], [H|R]) :-
member(H,T),!,
delete3(H,T,R1),
remove_duplicates(R1,R).
remove_duplicates([H|T],[H|R]):-
remove_duplicates(T,R).
2番目の述語では、ヘッド変数*(H)*がリスト*(T)*の末尾のメンバーであるかどうかを確認します。そうである場合、最初の述語を呼び出して、末尾にあるヘッド変数と等しいすべての変数を削除します。
% remdup(List, List_No_duplicates).
remdup([],[]).
remdup([H|T],Lnd):- rd1(H,T,T1), remdup(T1,Tnd),Lnd=[H|Tnd].
% rd1(X,L,Lr) removes all occurance of X in List L and store result in List Lr
rd1(_,[],[]).
rd1(X,[X|T],Lx):- rd1(X,T,Lx).
rd1(X,[Y|T],Lx):- rd1(X,T,Lx1),Lx=[Y|Lx1].
仕組み-述語remdup
指定されたリストの最初の要素Hを取得し、テールパーツT内のそのすべての出現を削除します-この結果をリストT1に格納します。そして
T1ストアの結果でremdupを再帰的に呼び出してTndに格納します。そして
要素HをTndに追加します。Tndは、実際にはremdupの再帰呼び出しによって変更されたテールパーツTであり、すでにすべての重複がなく、Hの出現は含まれていません。
述語-rd1
list_to_set/2
またはsort/2
ここでの回答で述べたように。