std::transformとは?
- 指定されたイテレータ範囲内の要素に関数を適用するための関数。
- これにより、for文を使わずvectorを2倍するといったことが可能になります。
- 参考サイト:transform - cpprefjp C++日本語リファレンス
使用例1:vectorの全要素を1だけ加算
- 今回使用するstd::transformの引数を以下の表に示します。
第1引数 | コピー元のイテレータの先頭 |
---|---|
第2引数 | コピー元のイテレータの末尾 |
第3引数 | コピー先のイテレータの先頭 |
第4引数 | ラムダ式 or 関数 |
ラムダ式使用の場合
コピー元(v1)、コピー先(v2)とすれば、引数は以下のようにします。
第1引数 | v1.begin() |
---|---|
第2引数 | v1.end() |
第3引数 | v2.begin() (v1.begin()にすればv2へのコピーではなくv1の更新が可能) |
第4引数 | [](int x) { return x + 1; } |
ソースコード
#include <algorithm> #include <iostream> #include <vector> int main() { // 配列の宣言 std::vector<int> v1{3, 5, 6, 7, 8}; std::vector<int> v2(v1.size()); //サイズ設定はあらかじめしておく // v1を1だけ加算して、v2(v1)に格納(ラムダ式使用) std::transform( v1.begin(), v1.end(), v2.begin(), //v1.begin()とすればv1を更新できる [](int x) { return x + 1; } ); // v2の表示 std::cout << "v2 = { "; for (int i = 0; i < v2.size(); i++) { std::cout << v2[i] << ", "; } puts("}"); // v1の表示をする場合はこちら // std::cout << "v1 = { "; // for (int i = 0; i < v1.size(); i++) { // std::cout << v1[i] << ", "; // } // puts("}"); }
実行結果
v2 = { 4, 6, 7, 8, 9, }
関数使用の場合
- ラムダ式の箇所を関数に置き換えるだけ。
ソースコード(実行結果は同じなため省略)
#include <algorithm> #include <iostream> #include <vector> // 引数を1だけ増やす関数 int increment(int n){ return n + 1; } int main() { // 配列の宣言 std::vector<int> v1{3, 5, 6, 7, 8}; std::vector<int> v2(v1.size()); //サイズ設定はあらかじめしておく // v1を1だけ加算して、v2(v1)に格納(関数使用) std::transform( v1.begin(), v1.end(), v2.begin(), increment ); // v2の表示 std::cout << "v2 = { "; for (int i = 0; i < v2.size(); i++) { std::cout << v2[i] << ", "; } puts("}"); }
使用例2:文字列を小文字⇒大文字変換
- stringに対しても適用できます。
- 大文字⇒小文字は「tolower」、小文字⇒大文字は「toupper」でできます。
- 別記事に詳しくまとめたので良ければ(露骨な宣伝)⇒C++ stringの大文字⇔小文字変換 - パハットノート
第1引数 | s1.begin() |
---|---|
第2引数 | s1.end() |
第3引数 | s2.begin() |
第4引数 | std::toupper(c) |
ソースコード
#include <algorithm> #include <iostream> int main() { std::string s1 = "twitter"; std::string s2 = s1; //s1と同じ文字数必要なのでs1をコピーした // transformを使う場合 std::transform( s1.begin(), s1.end(), s2.begin(), //s1.begin()とすればs1を更新できる [](char c) { return std::toupper(c); } // 大文字⇒小文字変換の場合はtolower ); // 表示 std::cout << "s1 = " << s1 << std::endl; std::cout << "s2 = " << s2 << std::endl; }
実行結果
s1 = twitter s2 = TWITTER
使用例3:2つのvectorの和を計算
- 引数を5つにすることで、2つのvectorの和を計算するといったことが可能です。
- 今回使用するstd::transformの引数を以下の表に示します。
- 例)v1とv2の和をv3に保存
第1引数 | v1.begin() |
---|---|
第2引数 | v1.end() |
第3引数 | v2.begin() |
第4引数 | v3.begin() |
第5引数 | 関数 or ラムダ式 |
ソースコード
#include <algorithm> #include <iostream> #include <vector> int main() { // 配列の宣言 std::vector<int> v1{3, 5, 6, 7, 8}; std::vector<int> v2{-2, 1, 3, 2, 4}; std::vector<int> v3(v1.size()); //サイズ設定はあらかじめしておく // v3 = v1 + v2 std::transform( v1.begin(), v1.end(), v2.begin(), v3.begin(), [](int x, int y) { return x + y; } ); // v2の表示 std::cout << "v3 = { "; for (int i = 0; i < v3.size(); i++) { std::cout << v3[i] << ", "; } puts("}"); }
実行結果
v3 = { 1, 6, 9, 9, 12, }
使用例4:set⇒vector変換
- setの要素をvectorにコピーすることも可能です。。
- コピー元のsetをst、コピー先のベクトルをvとすると引数は次のようになります。
第1引数 | st.begin() |
---|---|
第2引数 | st.end() |
第3引数 | v.begin() |
第4引数 | 関数 or ラムダ式 |
ソースコード
#include <algorithm> #include <iostream> #include <vector> #include <set> int main() { std::set<int> st{ 10, 3, 6, 5, 8 }; std::vector<int> v(st.size()); //サイズ設定はあらかじめしておく std::transform( st.begin(), st.end(), v.begin(), [](int x) { return x; } ); // vの表示 std::cout << "v = { "; for (int i = 0; i < v.size(); i++) { std::cout << v[i] << ", "; } std::cout << "}" << std::endl; }
実行結果
v = { 3, 5, 6, 8, 10, }