## 13.5 削除アルゴリズム

`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 ファイルにあります。

### 13.5.1 不要な要素を削除する

アルゴリズム `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());
    }

### 13.5.2 等価の連続要素を削除する

アルゴリズム `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());
    }

Copyright (c) 1998, Rogue Wave Software, Inc.
このマニュアルに関する誤りのご指摘やご質問は、電子メールにてお送りください。
OEM リリース, 1998 年 6 月