LoginSignup
1
2

More than 3 years have passed since last update.

C++ STL mapのコード集

Last updated at Posted at 2020-06-09

概要

STL(Standard Template Library)のmap関係のコード集です。対応確認環境はMicrosoft Visual Studio 2019 Communityのstd:c++latest (C++20 draft)です。最新のC++では制約が異なる可能性があります。

共通事項

  • using namespace std;によりstd::は省略しています。
  • insert_iteratorinsert_iterator(m, begin(m))insert_iterator(m, end(m))のどちらでも作成できます。inserterも同様です。
  • type var{...};type var = {...};と同様です。

出力用の関数

出力用に次の関数を定義しています。共通部分なので以降のコードでは省略します。

mapの出力

template <typename KeyT, typename MappedT>
void output(const map<KeyT, MappedT>& map)
{
    for (const auto& [key, value] : map)
    {
        wcout << key << L", " << value << endl;
    }
}

vectorの出力

範囲forcopyostream_iteratorの2種類が使用できます。

範囲for
template <typename T>
void output(const vector<T>& v)
{
    for (const auto& i : v)
    {
        wcout << i << endl;
    }
}
copyとostream_iterator
template <typename T>
void output(const vector<T>& v)
{
    copy(cbegin(v), cend(v),
        ostream_iterator<T, wchar_t>(wcout, L"\r\n"));
}

一般的な制約

  • ラムダ式の引数は構造化束縛できません。mapの要素を引数としたラムダ式ではconst auto& pairを使い、必要に応じてラムダ式内で構造化束縛const auto& [key, value] = pair;します。
  • 範囲forでは構造化束縛できます。

mapのコピー

コンストラクタにイテレータを渡すと任意の範囲をコピーできます。キーは昇順でソートされることに注意してください。

全体のコピー

#include <algorithm>
#include <iostream>
#include <map>

using namespace std;

template <typename KeyT, typename MappedT>
void output(const map<KeyT, MappedT>& map);

int main()
{
    map<int, int> m1{{0, 0}, {1, 1}, {2, 2}};
    map<int, int> m2(cbegin(m1), cend(m1));

    output(m2);

    return 0;
}
出力
0, 0
1, 1
2, 2

部分のコピー

cbegincendnextprevを適用して先頭からN個や末尾からN個を飛ばしてコピーできます。

#include <iostream>
#include <map>

using namespace std;

template <typename KeyT, typename MappedT>
void output(const map<KeyT, MappedT>& map);

int main()
{
    map<int, int> m1{{0, 0}, {1, 1}, {2, 2}, {3, 3}, {4, 4}};
    // 先頭から2個、末尾から1個を飛ばしてコピー
    map<int, int> m2(next(cbegin(m1), 2), prev(cend(m1), 1));

    output(m2);

    return 0;
}
出力
2, 2
3, 3

逆順でコピー

crbegincrendを適用して逆順でコピーできます。nextprevも適用可能です。出力時はキーが昇順ソートされることに注意してください。

#include <iostream>
#include <map>

using namespace std;

template <typename KeyT, typename MappedT>
void output(const map<KeyT, MappedT>& map);

int main()
{
    map<int, int> m1{{0, 0}, {1, 1}, {2, 2}, {3, 3}, {4, 4}};
    // 逆順の末尾は{0, 0}なのでprev(crend(m1), 1)で除外されます。
    map<int, int> m2(crbegin(m1), prev(crend(m1), 1));

    output(m2);

    return 0;
}

出力
1, 1
2, 2
3, 3
4, 4

mapから別のmapへコピーして追加

  • ただのコピーして追加はcopymap::insertでも可能ですが、応用が効くのはtransformです。
  • いずれの方法にもnextprevcrbegincrendのような関数を適用できます。

transformの使用

#include <algorithm>
#include <iterator>
#include <iostream>
#include <map>

using namespace std;

template <typename KeyT, typename MappedT>
void output(const map<KeyT, MappedT>& map);

int main()
{
    map<int, int> m1{{0, 0}, {1, 1}, {2, 2}};

    map<int, int> m2;
    transform(cbegin(m1), cend(m1), inserter(m2, end(m2)),
        [](const auto& kv) {
            return kv;
        });

    output(m2);

    return 0;
}
出力
0, 0
1, 1
2, 2

ラムダ式内で構造化束縛

クラステンプレートの型推論(return pair(key, value))

ラムダ式内で構造化束縛すると次のようになります。戻り値ではkeyvalueからpairを作成する必要があります。ラムダ式の戻り値の型は省略できます。

#include <algorithm>
#include <iterator>
#include <iostream>
#include <map>

using namespace std;

template <typename KeyT, typename MappedT>
void output(const map<KeyT, MappedT>& map);

int main()
{
    map<int, int> m1{{0, 0}, {1, 1}, {2, 2}};

    map<int, int> m2;
    transform(cbegin(m1), cend(m1), insert_iterator(m2, end(m2)),
        [](const auto& kv) {
            const auto& [key, value] = kv;
            return pair(key, value);
        });

    output(m2);

    return 0;
}
出力
0, 0
1, 1
2, 2

生成関数(return make_pair(key, value))

戻り値はpairコンストラクタの代わりにmake_pair生成関数を使うこともできます。

#include <algorithm>
#include <iterator>
#include <iostream>
#include <map>

using namespace std;

template <typename KeyT, typename MappedT>
void output(const map<KeyT, MappedT>& map);

int main()
{
    map<int, int> m1{{0, 0}, {1, 1}, {2, 2}};

    map<int, int> m2;
    transform(cbegin(m1), cend(m1), insert_iterator(m2, end(m2)),
        [](const auto& kv) {
            const auto& [key, value] = kv;
            return make_pair(key, value);
        });

    output(m2);

    return 0;
}
出力
0, 0
1, 1
2, 2

return {...}

戻り値には初期化子リストも指定できます。ただし、型推論のためにラムダ式の戻り値の型を明記する必要があります。

#include <algorithm>
#include <iterator>
#include <iostream>
#include <map>

using namespace std;

template <typename KeyT, typename MappedT>
void output(const map<KeyT, MappedT>& map);

int main()
{
    map<int, int> m1{{0, 0}, {1, 1}, {2, 2}};

    map<int, int> m2;
    transform(cbegin(m1), cend(m1), insert_iterator(m2, end(m2)),
        [](const auto& kv) -> decltype(m2)::value_type {
            const auto& [key, value] = kv;
            return {key, value};
        });

    output(m2);

    return 0;
}
出力
0, 0
1, 1
2, 2

copyの使用

#include <algorithm>
#include <iostream>
#include <map>
#include <vector>

using namespace std;

template <typename KeyT, typename MappedT>
void output(const map<KeyT, MappedT>& map);

int main()
{
    map<int, int> m1{{0, 0}, {1, 1}, {2, 2}};
    map<int, int> m2;
    copy(cbegin(m1), cend(m1), insert_iterator(m2, end(m2)));

    output(m2);

    return 0;
}

map::insertの使用

#include <iostream>
#include <map>

using namespace std;

template <typename KeyT, typename MappedT>
void output(const map<KeyT, MappedT>& map);

int main()
{
    map<int, int> m1{{0, 0}, {1, 1}, {2, 2}};
    map<int, int> m2;
    m2.insert(cbegin(m1), cend(m1));

    output(m2);

    return 0;
}

値をwstring型に変換したmapを作成する

to_wstringを使います。既存のmapを指定することで要素の追加も可能です。

#include <algorithm>
#include <iterator>
#include <iostream>
#include <string>
#include <map>

using namespace std;

template <typename KeyT, typename MappedT>
void output(const map<KeyT, MappedT>& map);

int main()
{
    map<int, int> m1{{0, 0}, {1, 1}, {2, 2}};

    map<int, wstring> m2;
    transform(cbegin(m1), cend(m1), insert_iterator(m2, end(m2)),
        [](const auto& kv) {
            const auto& [key, value] = kv;
            return pair(key, to_wstring(value));
        });

    output(m2);

    return 0;
}
出力
0, 0
1, 1
2, 2

値をstring型に変換したmapを作成する

to_stringを使います。既存のmapを指定することで要素の追加も可能です。

#include <algorithm>
#include <iterator>
#include <iostream>
#include <string>
#include <map>

using namespace std;

template <typename KeyT, typename MappedT>
void output(const map<KeyT, MappedT>& map);

int main()
{
    map<int, int> m1{{0, 0}, {1, 1}, {2, 2}};

    map<int, string> m2;
    transform(cbegin(m1), cend(m1), insert_iterator(m2, end(m2)),
        [](const auto& kv) {
            const auto& [key, value] = kv;
            return pair(key, to_string(value));
        });

    output(m2);

    return 0;
}
出力
0, 0
1, 1
2, 2

キーや値をvectorへ変換する

キーをvectorに変換する

#include <algorithm>
#include <iterator>
#include <iostream>
#include <map>
#include <vector>

using namespace std;

template <typename T>
void output(const vector<T>& v)

int main()
{
    map<int, int> m1{{0, 0}, {1, 1}, {2, 2}};

    vector<decltype(m1)::key_type> keys;
    transform(cbegin(m1), cend(m1), back_insert_iterator(keys),
        [](const auto& kv) {
            const auto& [key, value] = kv;
            return key;
        });

    output(keys);

    return 0;
}
出力
0
1
2

値をvectorへ変換する

値の型はmap<>::mapped_typeです。map<>::value_typeはキーと値のペアのpair型です。

#include <algorithm>
#include <iterator>
#include <iostream>
#include <map>
#include <vector>

using namespace std;

template <typename KeyT, typename MappedT>
void output(const map<KeyT, MappedT>& map);

int main()
{
    map<int, int> m1{{0, 0}, {1, 1}, {2, 2}};

    vector<decltype(m1)::mapped_type> values;
    transform(cbegin(m1), cend(m1), back_insert_iterator(values),
        [](const auto& kv) {
            const auto& [key, value] = kv;
            return value;
        });

    output(values);

    return 0;
}

キーと値からmapを作成する

transformの2入力イテレーター版で実現できます。

#include <algorithm>
#include <iostream>
#include <map>
#include <vector>

using namespace std;

template <typename KeyT, typename MappedT>
void output(const map<KeyT, MappedT>& map);

int main()
{
    vector keys{0, 1, 2};
    vector values{0, 1, 2};

    map<int, int> m1;
    transform(cbegin(keys), cend(keys), cbegin(values),
        insert_iterator(m1, end(m1)),
        [](const auto& key, const auto& value) {
            return pair(key, value);
        });

    output(m2);

    return 0;
}
出力
0, 0
1, 1
2, 2

入力イテレータ1が入力イテレーター2より長い場合は実行時エラーが発生することに注意してください。

入力イテレータ1>入力イテレーター2
vector keys{0, 1, 2, 3};
vector values{0, 1, 2};
// 異常終了
入力イテレータ1<入力イテレーター2
vector keys{0, 1, 2};
vector values{0, 1, 2, 3};
// 入力イテレータ2の超過した要素が無視
// 0, 0
// 1, 1
// 2, 2
1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2