zoukankan      html  css  js  c++  java
  • C++/C++11中std::transform的使用

    std::transform在指定的范围内应用于给定的操作,并将结果存储在指定的另一个范围内。要使用std::transform函数需要包含<algorithm>头文件。

    以下是std::transform的两个声明,一个是对应于一元操作,一个是对应于二元操作:

    template <class InputIterator, class OutputIterator, class UnaryOperation>
      OutputIterator transform (InputIterator first1, InputIterator last1,
                                OutputIterator result, UnaryOperation op);
        
    template <class InputIterator1, class InputIterator2,
              class OutputIterator, class BinaryOperation>
      OutputIterator transform (InputIterator1 first1, InputIterator1 last1,
                                InputIterator2 first2, OutputIterator result,
                                BinaryOperation binary_op);

      对于一元操作,将op应用于[first1, last1)范围内的每个元素,并将每个操作返回的值存储在以result开头的范围内。给定的op将被连续调用last1-first1次。op可以是函数指针或函数对象或lambda表达式。

      如op的一个实现 即将[first1, last1)范围内的每个元素加5,然后依次存储到result中。

    int op_increase(int i) {return (i + 5)};

      调用std::transform的方式如下:

    std::transform(first1, last1, result, op_increase);

      对于二元操作,使用[first1, last1)范围内的每个元素作为第一个参数调用binary_op,并以first2开头的范围内的每个元素作为第二个参数调用binary_op,每次调用返回的值都存储在以result开头的范围内。给定的binary_op将被连续调用last1-first1次。binary_op可以是函数指针或函数对象或lambda表达式。

      如binary_op的一个实现即将first1和first2开头的范围内的每个元素相加,然后依次存储到result中。

     int op_add(int, a, int b) {return (a + b)};

      std::transform支持in place,即result和first1指向的位置可以是相同的。std::transform的主要作用应该就是省去了我们自己写for循环实现。

      以下是摘自对std::transform的英文解释:

    /*
    // reference: http://en.cppreference.com/w/cpp/algorithm/transform
    template< class InputIt, class OutputIt, class UnaryOperation >
    OutputIt transform( InputIt first1, InputIt last1, OutputIt d_first, UnaryOperation unary_op )
    {
      while (first1 != last1) {
      *d_first++ = binary_op(*first1++, *first2++);
      }
      return d_first;
    }
    template< class InputIt1, class InputIt2, class OutputIt, class BinaryOperation >
    OutputIt transform( InputIt1 first1, InputIt1 last1, InputIt2 first2, OutputIt d_first, BinaryOperation binary_op );
    std::transform applies the given function to a range and stores the result in another range, beginning at d_first.
    (1): The unary operation unary_op is applied to the range defined by [first1, last1).
    (2): The binary operation binary_op is applied to pairs of elements from two ranges:
         one defined by [first1, last1) and the other beginning at first2.
    Parameters:
      first1, last1: the first range of elements to transform
      first2: the beginning of the second range of elements to transform
      d_first:the beginning of the destination range, may be equal to first1 or first2
      unary_op: unary operation function object that will be applied.
      binary_op: binary operation function object that will be applied.
    Return value: Output iterator to the element past the last element transformed.
    std::for_each: ignores the return value of the function and guarantees order of execution.
    std::transform: assigns the return value to the iterator, and does not guarantee the order of execution.
    */

      以下是std::transform用法举例:

    #include "transform.hpp"
    #include <algorithm> // std::transform
    #include <string>
    #include <cctype> // std::toupper
    #include <iostream>
    #include <vector>
    #include <functional> // std::plus c++14
     
    int test_transform1()
    {
        std::string s("Hello");
        std::transform(s.begin(), s.end(), s.begin(),
            [](unsigned char c) { return std::toupper(c); });
        std::cout << s << std::endl; // HELLO
     
        std::transform(s.begin(), s.end(), s.begin(), ::tolower);
        std::cout << s << std::endl; // hello
     
        ////////////////////////////////
        std::vector<int> arr{ 1, 3, 5 };
        std::vector<int> arr2{ 1, 3, 5 };
        std::vector<int> arr3{ 1, 3, 5 };
     
        std::transform(arr.begin(), arr.end(), arr.begin(),
            [](int d) -> int {return d * 5; }); // for_each
        for (auto value : arr) {
            std::cout << value << "    "; // 5 15 25
        }
        std::cout<<std::endl;
     
        std::for_each(arr2.begin(), arr2.end(), [](int& a) {a *= 5; });
        for (auto value : arr2) {
            std::cout << value << "    "; // 5 15 25
        }
        std::cout << std::endl;
     
        for (auto& value : arr3) {
            value *= 5;
        }
        for (auto value : arr3) {
            std::cout << value << "    "; // 5 15 25
        }
        std::cout << std::endl;
     
        std::vector<std::string> names = { "hi", "test", "foo" };
        std::vector<std::size_t> name_sizes;
     
        ///////////////////////////
        std::transform(names.begin(), names.end(), std::back_inserter(name_sizes),
            [](std::string name) { return name.size(); });
        for (auto value : name_sizes) {
            std::cout << value << "    "; // 2 4 3
        }
        std::cout << std::endl;
     
        std::for_each(name_sizes.begin(), name_sizes.end(), [](std::size_t name_size) {
            std::cout << name_size << "    "; // 2 4 3
        });
        std::cout << std::endl;
     
        return 0;
    }
     
    /////////////////////////////////////////////////////////
    // reference: http://www.cplusplus.com/reference/algorithm/transform/
    static int op_increase(int i) { return ++i; }
     
    int test_transform2()
    {
        std::vector<int> foo;
        std::vector<int> bar;
     
        // set some values:
        for (int i = 1; i<6; i++)
            foo.push_back(i * 10); // foo: 10 20 30 40 50
     
        bar.resize(foo.size()); // allocate space
     
        std::transform(foo.begin(), foo.end(), bar.begin(), op_increase);
        // bar: 11 21 31 41 51
     
        // std::plus adds together its two arguments:
        std::transform(foo.begin(), foo.end(), bar.begin(), foo.begin(), std::plus<int>());
        // foo: 21 41 61 81 101
     
        std::cout << "foo contains:";
        for (std::vector<int>::iterator it = foo.begin(); it != foo.end(); ++it)
            std::cout << ' ' << *it; // 21 41 61 81 101
        std::cout << '
    ';
     
        return 0;
    }
     





    本文来自博客园,作者:Mr-xxx,转载请注明原文链接:https://www.cnblogs.com/MrLiuZF/p/13338848.html

  • 相关阅读:
    PointToPointNetDevice doesn't support TapBridgeHelper
    NS3系列—10———NS3 NodeContainer
    NS3系列—9———NS3 IP首部校验和
    NS3系列—8———NS3编译运行
    【习题 7-6 UVA
    【Good Bye 2017 C】 New Year and Curling
    【Good Bye 2017 B】 New Year and Buggy Bot
    【Good Bye 2017 A】New Year and Counting Cards
    【Educational Codeforces Round 35 D】Inversion Counting
    【Educational Codeforces Round 35 C】Two Cakes
  • 原文地址:https://www.cnblogs.com/MrLiuZF/p/13338848.html
Copyright © 2011-2022 走看看