C++ transform函数

前言

在某些应用场景中,我们需要将某一容器内的元素放入另一个容器中,但是这两个容器的数据类型又是不同的。常见的解决方式就是循环遍历源容器,并在循环中改变元素的数据类型,同时放入目的容器中。
C++给我们提供了另一种方式,其主要原理和常见的解决方式是一样的,但是在代码上更加美观,那就是使用std::transform;

主要内容

std::transform函数原型

单范围版本

template< class InputIt, class OutputIt, class UnaryOperation >  
OutputIt transform( InputIt first1, InputIt last1, OutputIt d_first, UnaryOperation unary_op );

  • InputIt 是输入迭代器类型,指向输入范围的开始和结束。
  • OutputIt 是输出迭代器类型,指向存储结果的范围的开始。
  • UnaryOperation 是一个一元操作,接受输入范围中的一个元素作为参数,并返回转换后的结果。这可以是一个函数、函数对象、Lambda表达式等。
  • first1 和 last1 分别指定输入范围的开始和结束迭代器。
  • 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 );
  • 这个版本与单范围版本类似,但增加了第二个输入范围 InputIt2 和它的起始迭代器 first2
  • BinaryOperation 是一个二元操作,接受两个输入范围中的对应元素作为参数,并返回结合后的结果。
  • 其余参数与单范围版本相同。

函数示例

示例一(单范围)

std::vector<int> src_vec = {1,2,3,4,5};
std::vector<std::string> dec_vec(src_vec.size());

std::transform(src_vec.begin(), src_vec.end(), dec_vec.begin(), [](int x){
	return std::to_string(x);
});

在这里我们使用了lambda函数来作为UnaryOperation

示例二(单范围)

std::string ToString(int x)
{
	return std::to_string(x);
}

int main(void)
{
	std::vector<int> src_vec = {1,2,3,4,5};
	std::vector<std::string> dec_vec(src_vec.size());

	std::transform(src_vec.begin(), src_vec.end(), dec_vec.begin(), ToString);
}

在这里我们使用了一个函数作为UnaryOperation

示例三(双范围)

std::vector<int> vec1 = {1, 2, 3, 4, 5};  
std::vector<int> vec2 = {10, 20, 30, 40, 50};  
std::vector<int> result(vec1.size());  

std::transform(vec1.begin(), vec1.end(), vec2.begin(), result.begin(),
	std::plus<int>());

transform内没有指定vec2的范围,但是vec2依托于vec1的范围;
如果vec1的size 大于 vec2的size,并不会影响transform。

    std::vector<int> vec1 = {1, 2, 3, 4, 5};
    std::vector<int> vec2 = {10, 20, 30, 40};
    std::vector<int> result(vec1.size());

    std::transform(vec1.begin(), vec1.end(), vec2.begin(), result.begin(),
                   std::plus<int>()); // 将vec1和vec2中对应位置的元素相加 

    for (auto item : result)
    {
        std::cout << item << " , ";
    }

	// 程序结果
	// 11 , 22 , 33 , 44 , 5 ,

注意事项

  • 目的容器一定要在声明时 提前设置容器容量
### C++ STL `transform` 函数的用法 `std::transform` 是 C++ 标准模板库(STL)中的一个重要算法函数,用于对输入范围内的元素应用某个操作并将其结果存储到目标范围内。它通常被用来实现数据转换的功能。 #### 基本语法 以下是 `std::transform` 的两种主要形式: 1. **单输入序列版本** ```cpp OutputIterator transform(InputIterator first1, InputIterator last1, OutputIterator result, UnaryOperation op); ``` 这一版本接受一个单一的输入序列 `[first1, last1)` 和一个返回值的操作对象 `op`,并将该操作应用于每个元素后存入由 `result` 开始的目标位置。 2. **双输入序列版本** ```cpp OutputIterator transform(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, OutputIterator result, BinaryOperation binary_op); ``` 此版本接收两个输入序列 `[first1, last1)` 和 `[first2, first2 + (last1 - first1))`,以及二元运算符 `binary_op` 来组合来自这两个序列的数据,并将结果写入目标容器。 #### 使用示例 ##### 单输入序列变换 下面是一个简单的例子,展示如何通过 `std::transform` 将向量中的所有整数加倍: ```cpp #include <iostream> #include <vector> #include <algorithm> int main() { std::vector<int> vec = {1, 2, 3, 4}; std::vector<int> doubled(vec.size()); auto double_func = [](int x) -> int { return x * 2; }; std::transform(vec.begin(), vec.end(), doubled.begin(), double_func); for(auto num : doubled){ std::cout << num << ' '; } } ``` 上述代码定义了一个 lambda 表达式来表示乘以两倍的操作[^2],并通过调用 `std::transform` 对原始数组执行此操作。 ##### 双输入序列变换 另一个常见的场景是对两个集合做逐项加法或其他类似的二元运算: ```cpp #include <iostream> #include <vector> #include <algorithm> int main(){ std::vector<int> v1 = {10, 20, 30}, v2 = {1, 2, 3}; std::vector<int> sums(v1.size()); std::transform(v1.begin(), v1.end(), v2.begin(), sums.begin(), std::plus<>()); for(int sum_val : sums){ std::cout << sum_val << ' '; // 输出应为:11 22 33 } return 0; } ``` 这里我们利用了 `<functional>` 头文件里的预定义泛型算术运算器类 `std::plus`[^1]。 #### 性能考量 尽管 `std::transform` 提供了极大的灵活性和便利性,在某些情况下它的性能可能不如手动循环优化得那么好。如果发现调试模式下运行速度较慢,则可以考虑调整编译选项或者寻找其他替代方案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一直在找资料的菜鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值