remove() アルゴリズムと unique() アルゴリズムを初めて使用する際には、多少混乱するかもしれません。どちらのアルゴリズムも、シーケンスのサイズを縮小せずに、シーケンスから特定の値の削除を要求します。またどちらも、保持される値をシーケンスの先頭に移動して、このシーケンスの終端位置を定義する反復子を返します。この反復子の後に続くのは、未変更の元のシーケンスの値だけです。汎用アルゴリズムには、処理するコンテナについての知識がないため、この反復子が必要です。汎用アルゴリズムには汎用反復子しかありません。これは汎用アルゴリズムに伴う問題の 1 つです。一般に、この反復子の結果は、コンテナの erase() メンバー関数の引数として使用され、値を反復子からシーケンスの終わりに移動します。
これを簡単な例を挙げて説明します。シーケンス 1 2 3 4 5 6 7 8 9 10 から偶数を削除する場合、remove_if() アルゴリズムを使用することができます。このアルゴリズムを適用すると、結果は次のシーケンスとなります。
1 3 5 7 9 | 6 7 8 9 10
この垂直バーは、remove_if() アルゴリズムが返す反復子の位置を示しています。バーの前にある 5 つの要素は、希望どおりの結果を示していますが、バーの後にある 5 つの要素は、単にこの位置の元の内容であることに注意してください。この反復子の値をシーケンスの終わりの反復子とともに erase() の引数として使用することによって、不要な値を削除し、希望の結果を得ることができます。
ここで説明したアルゴリズムには、いずれも代替コピーバージョンがあります。アルゴリズムの コピーバージョンは、元の要素を未変更のまま保持し、保持された要素を出力シーケンスにコピーします。
注 : この節で説明する関数例は、alg4.cpp ファイルにあります。
アルゴリズム remove() は、シーケンスから不要な値を削除します。find() アルゴリズムと同様に、削除されるのは特定の定数や述語に一致する値です。引数型の宣言は次のとおりです。
ForwardIterator remove (ForwardIterator first, ForwardIterator last, const T &); ForwardIterator remove_if (ForwardIterator first, ForwardIterator last, Predicate);
アルゴリズム remove() は、値をシーケンスの先頭にコピーして、削除される要素の位置を上書きします。削除されない要素はすべて、その相対順序を保持します。値が検査されると、シーケンスの残りの部分は未変更のままになります。演算結果として返される反復子は、新規シーケンスの終わりの位置を示します。たとえば、シーケンス 1 2 4 3 2 から要素 2 を削除すると、結果のシーケンスは 1 4 3 3 2 となり、反復子が 2 番目の 3 を表す結果として返されます。この値を erase() の引数として使用して、プログラム例に示すように、残りの要素 3 および 2 を削除することができます。
アルゴリズムのコピーバージョンは、値を同じ位置で変換せずに、出力シーケンスにコピーします。
OutputIterator remove_copy (InputIterator first, InputIterator last, OutputIterator result, const T &); OutputIterator remove_copy_if (InputIterator first, InputIterator last, OutputIterator result, Predicate);
以下のプログラムで remove() の使用方法を説明します。
void remove_example () // 削除アルゴリズムの使用方法を説明する // 完全なソースコードについては alg4.cpp を参照 { // 数値リストを作成する int data[] = {1, 2, 4, 3, 1, 4, 2}; list<int> aList; copy (data, data+7, inserter(aList, aList.begin())); // 2 を削除し新規リストにコピーする list<int> newList; remove_copy (aList.begin(), aList.end(), back_inserter(newList), 2); // 同じ位置で 2 を削除する list<int>::iterator where; where = remove (aList.begin(), aList.end(), 2); aList.erase(where, aList.end()); // すべての偶数値を削除する where = remove_if (aList.begin(), aList.end(), isEven); aList.erase(where, aList.end()); }
アルゴリズム unique() は、線形シーケンスを移動して、等価要素のすべて連続グループから、最初の要素を除くすべての要素を削除します。引数シーケンスは、次の反復子で定義されます。
ForwardIterator unique (ForwardIterator first, ForwardIterator last [, BinaryPredicate ] );
このアルゴリズムはコレクションを移動するので、要素はシーケンスの先頭に移動され、既存の要素が上書きされます。すべての一意の値が識別され、残りのシーケンスは未変更のままです。たとえば、シーケンス 1 3 3 2 2 2 4 は、1 3 2 4 | 2 2 4 に変更されます。ここでは、反復子の結果の値が返す位置を垂直バーで示しています。この位置は、一意のシーケンスの終わりと残りの要素の始まりを示しています。ほとんどのコンテナで、このアルゴリズムが返す値は後の erase() 呼び出しの引数として使用され、不要な要素をコレクションから削除します。これを、プログラム例で説明します。
このアルゴリズムのコピーバージョンは、一意の値を同じ位置で変更せずに、出力反復子に移動します。list または multiset の変換では、挿入反復子を使用して、出力反復子のコピー演算を挿入に変更することができます。
OutputIterator unique_copy (InputIterator first, InputIterator last, OutputIterator result [, BinaryPredicate ] );
これを次のプログラム例で説明します。
void unique_example () // unique アルゴリズムの使用方法を説明する // 完全なソースコードについては alg4.cpp を参照 { // まず値のリストを作成する int data[] = {1, 3, 3, 2, 2, 4}; list<int> aList; set<int> aSet; copy (data, data+6, inserter(aList, aList.begin())); // 一意の要素を set にコピーする unique_copy (aList.begin(), aList.end(), inserter(aSet, aSet.begin())); // 同じ位置で一意の要素をコピーする list<int>::iterator where; where = unique(aList.begin(), aList.end()); // 終端の値を削除する aList.erase(where, aList.end()); }