パープルハット

※当サイトではGoogleアドセンス広告を利用しています

C++ std::transformの使い方



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:文字列を小文字⇒大文字変換

第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, }