transform可以将函数应用于序列的元素上,并将返回值保存到另一个序列,返回值为输出序列保存的最后一个元素的下一个位置。和for_each的区别在于
1、for_each函数返回值必须为void,可以通过参数修改原序列的值
2、transform的二元函数必须返回一个值,同时也能将结果保存到另一个序列
3、transform中输出序列中的元素类型可以和输入序列中的元素类型不同
4、transform可以有两个输入序列,支持二元函数
以下为代码示例,不多说了
#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector>
#include <numeric>
#include <deque>
int main() {
#ifdef USE1
std::vector<double> deg_C{ 21.0,30.5,0.0,3.2,100.0 };
std::vector<double> deg_F(deg_C.size());
std::transform(deg_C.begin(), deg_C.end(), deg_F.begin(), [](double temp) {return 32.0 + 9.0 * temp / 5.0; }); //用begin的话要确保容器能装下所有元素
std::copy(deg_F.begin(), deg_F.end(), std::ostream_iterator<double>(std::cout, " "));
std::cout << std::endl;
std::cout << "--------------------------" << std::endl;
#elif defined USE2
std::vector<double> deg_C{ 21.0,30.5,0.0,3.2,100.0 };
std::vector<double> deg_F;
std::transform(deg_C.begin(), deg_C.end(), std::back_inserter(deg_F), [](double temp) {return 32.0 + 9.0 *temp / 5.0; }); //用back_inserter的话会在容器后面插入
std::copy(deg_F.begin(), deg_F.end(), std::ostream_iterator<double>(std::cout, " "));
std::cout << std::endl;
std::cout << "--------------------------" << std::endl;
#elif defined USE3 //处理完序列中的每个元素可以放到不同类型的另一个序列中,但是transform中的处理函数的返回类型必须和目标容器元素类型一致
std::vector<std::string> deg_C{"one","two","three","four","five"};
std::vector<size_t> deg_F;
std::transform(deg_C.begin(), deg_C.end(), std::back_inserter(deg_F), std::hash<std::string>()); //std::hash<T>()为定义在std::string中的一个hash函数对象
std::copy(deg_F.begin(), deg_F.end(), std::ostream_iterator<double>(std::cout, " "));
std::cout << std::endl;
std::cout << "--------------------------" << std::endl;
#elif defined USE4 //可以在transform所运用的函数中调用一个算法
std::deque<std::string> names{ "Stan Laurel", "Oliver Hardy", "Harold Lloyd" };
std::transform(names.begin(), names.end(), names.begin(), [](std::string& s) {std::transform(s.begin(), s.end(), s.begin(), ::toupper); return s; });
std::for_each(names.begin(), names.end(), [](std::string &s) {std::cout << s.data() << " "; });
std::cout << std::endl;
std::cout << "--------------------------" << std::endl;
#else //可以用两个输入序列做为输入序列
//计算正六边形的周长
using Point = std::pair<double, double>;
std::vector<Point> hexagon{ {1,2},{2,1},{3,1},{4,2},{3,3},{2,3},{1,2} }; //取前6个点做为第一个输入序列,后6个点做为第二个输入序列
std::vector<double> segments;
std::transform(hexagon.begin(), hexagon.end() - 1, hexagon.begin() + 1, std::back_inserter(segments),//第三个参数为第二个输入序列的开始迭代器,该序列元素个数至少等于第一个输入序列
[](Point &p1, Point &p2) {return std::sqrt((p1.first - p2.first)*(p1.first - p2.first) + (p1.second - p2.second) * (p1.second - p2.second)); });
std::copy(segments.begin(), segments.end(), std::ostream_iterator<double>(std::cout, " "));
std::cout << std::endl;
std::cout << std::accumulate(segments.begin(), segments.end(), 0.0) << std::endl;
#endif // DEBUG
return 0;
}