削除の STLアルゴリズム 解答ページ | Programming Place Plus C++編【標準ライブラリ】 第21章

トップページC++編

C++編で扱っている C++ は 2003年に登場した C++03 という、とても古いバージョンのものです。C++ はその後、C++11 -> C++14 -> C++17 -> C++20 と更新されており、今後も 3年ごとに更新されます。
なかでも C++11 での更新は非常に大きなものであり、これから C++ の学習を始めるのなら、C++11 よりも古いバージョンを対象にするべきではありません。特に事情がないなら、新しい C++ を学んでください。 当サイトでは、C++14 をベースにした新C++編を作成中です。

問題①

問題① {0, 1, 2, 1, 1} という5つの要素が格納された、vector、list、set、配列から、値が 1 の要素を削除する処理をそれぞれ作成してください。配列以外は、実際に要素を削除してください。また、STLアルゴリズムだけでなく、コンテナの持つ機能も考慮に入れてください。


#include <algorithm>
#include <iostream>
#include <vector>
#include <list>
#include <set>

namespace {
    void Println(int elem)
    {
        std::cout << elem << std::endl;
    }
}

int main()
{
    static const int DATA_NUM = 5;
    static const int REMOVE_TARGET_VALUE = 1;

    int array[DATA_NUM] = { 0, 1, 2, 1, 1 };

    std::vector<int> vec(array, array + DATA_NUM);
    std::list<int> lst(array, array + DATA_NUM);
    std::set<int> set(array, array + DATA_NUM);

    std::cout << "[vector]" << std::endl;

    vec.erase(std::remove(vec.begin(), vec.end(), REMOVE_TARGET_VALUE), vec.end());
    std::for_each(vec.begin(), vec.end(), Println);

    std::cout << "[list]" << std::endl;

    lst.remove(REMOVE_TARGET_VALUE);
    std::for_each(lst.begin(), lst.end(), Println);

    std::cout << "[set]" << std::endl;

    set.erase(REMOVE_TARGET_VALUE);
    std::for_each(set.begin(), set.end(), Println);

    std::cout << "[配列]" << std::endl;

    int* const pEnd = std::remove(array, array + DATA_NUM, REMOVE_TARGET_VALUE);
    std::for_each(array, pEnd, Println);
}

実行結果

[vector]
0
2
[list]
0
2
[set]
0
2
[配列]
0
2

特定の値を持った要素を削除するには、STLアルゴリズムの remove関数を使います。vector や配列に関してはこれでいいのですが、set や map のような連想コンテナには使用できないので、eraseメンバ関数を使用します。

list に関しては、STLアルゴリズムの remove関数を使うことはできますが、メンバ関数版があるので、そちらを使った方が効率的です。

問題②

問題② {0, -1, 2, -3, 4} という5つの要素が格納された、vector、list、set、配列から、負数の要素を削除する処理をそれぞれ作成してください。配列以外は、実際に要素を削除してください。また、STLアルゴリズムだけでなく、コンテナの持つ機能も考慮に入れてください。


#include <algorithm>
#include <iostream>
#include <vector>
#include <list>
#include <set>

namespace {
    bool IsNegative(int value)
    {
        return value < 0;
    }
    void Println(int elem)
    {
        std::cout << elem << std::endl;
    }
}

int main()
{
    static const int DATA_NUM = 5;

    int array[DATA_NUM] = { 0, -1, 2, -3, 4 };

    std::vector<int> vec(array, array + DATA_NUM);
    std::list<int> lst(array, array + DATA_NUM);
    std::set<int> set(array, array + DATA_NUM);

    std::cout << "[vector]" << std::endl;

    vec.erase(std::remove_if(vec.begin(), vec.end(), IsNegative), vec.end());
    std::for_each(vec.begin(), vec.end(), Println);

    std::cout << "[list]" << std::endl;

    lst.remove_if(IsNegative);
    std::for_each(lst.begin(), lst.end(), Println);

    std::cout << "[set]" << std::endl;

    std::set<int>::iterator it = set.begin();
    for (;;) {
        it = std::find_if(it, set.end(), IsNegative);
        if (it == set.end()) {
            break;
        }
        set.erase(it++);
    }
    std::for_each(set.begin(), set.end(), Println);

    std::cout << "[配列]" << std::endl;

    int* const pEnd = std::remove_if(array, array + DATA_NUM, IsNegative);
    std::for_each(array, pEnd, Println);
}

実行結果

[vector]
0
2
4
[list]
0
2
4
[set]
0
2
4
[配列]
0
2
4

ある条件に従って要素を削除するには、STLアルゴリズムの remove_if関数を使います。問題①と同じく、vector や配列はこれを使えば良いですが、連想コンテナの場合には代替手段が必要になります。

残念ながら、連想コンテナの eraseメンバ関数には、条件を指定できるものがないので、条件に合う要素を探して、1つ1つ削除していく必要があります。解答例では、find_if関数(第19章)を使って要素を探しています。

list の場合は、remove_ifメンバ関数を使うと簡単ですし、効率的です。


参考リンク


更新履歴

’2016/11/26 新規作成。



第21章のメインページへ

C++編のトップページへ

Programming Place Plus のトップページへ



はてなブックマーク に保存 Pocket に保存 Facebook でシェア
X で ポストフォロー LINE で送る noteで書く
rss1.0 取得ボタン RSS 管理者情報 プライバシーポリシー
先頭へ戻る