概要
STL(Standard Template Library)のmap
関係のコード集です。対応確認環境はMicrosoft Visual Studio 2019 Communityのstd:c++latest (C++20 draft)です。最新のC++では制約が異なる可能性があります。
共通事項
-
using namespace std;
によりstd::
は省略しています。 -
insert_iterator
はinsert_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
の出力
範囲for
、copy
とostream_iterator
の2種類が使用できます。
template <typename T>
void output(const vector<T>& v)
{
for (const auto& i : v)
{
wcout << i << endl;
}
}
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
部分のコピー
cbegin
やcend
にnext
やprev
を適用して先頭から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
逆順でコピー
crbegin
とcrend
を適用して逆順でコピーできます。next
やprev
も適用可能です。出力時はキーが昇順ソートされることに注意してください。
#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
へコピーして追加
- ただのコピーして追加は
copy
やmap::insert
でも可能ですが、応用が効くのはtransform
です。 - いずれの方法にも
next
やprev
、crbegin
やcrend
のような関数を適用できます。
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))
ラムダ式内で構造化束縛すると次のようになります。戻り値ではkey
、value
から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より長い場合は実行時エラーが発生することに注意してください。
vector keys{0, 1, 2, 3};
vector values{0, 1, 2};
// 異常終了
vector keys{0, 1, 2};
vector values{0, 1, 2, 3};
// 入力イテレータ2の超過した要素が無視
// 0, 0
// 1, 1
// 2, 2