C++ Transform - 详解

发布时间:2023-05-22

一、transform是什么:

在C++标准库中,transform函数是一个非常实用的算法。它可以将一个给定的范围(一个或多个容器)的每个元素应用到一个函数,并将该函数的结果存储在另一容器中,或者覆盖当前范围。代码如下:

template <class InputIterator, class OutputIterator, class UnaryOperator>
OutputIterator transform (InputIterator first1, InputIterator last1, OutputIterator result, UnaryOperator op);

其中,first1和last1构成了一个区间,称为源区间,表示一个向量或数组。result指向存储器中的目标序列,是另一个向量或数组。op是转换操作函数的对象。此函数的任务是将[first1,last1]内的每个元素转换为op(*i),其中i是[first1,last1]所覆盖区间的指向成员的迭代器。

二、transform与lambda表达式:

在应用transform函数时,我们可以使用lambda表达式作为操作函数。Lambda表达式是一种C++的函数表示方式,它可以定义小型匿名函数。即变量可以在lambda函数中定义,在不用命名这些变量的情况下,可以给它们附加一个函数(或操作符)来作为匿名函数体。例如:

std::vector<int> from{1,2,3,4,5};
std::vector<int> to(from.size());
std::transform(from.begin(), from.end(), to.begin(), [](int i){ return i * 2 ; });

这个例子中,lambda表达式[](int i) { return i * 2;}作为transform的第三个参数被传递。transform函数会取from序列中的每个元素,将它们传递给lambda表达式,并把返回结果赋值给to序列中相应位置的元素。在这个例子中,最终的结果将是to = [2,4,6,8,10]。这证明了,通过transform函数,我们可以轻松地使用lambda表达式对向量进行操作。

三、transform与自定义函数:

在使用transform函数时,我们还可以使用用户自定义的函数作为操作函数。在使用自定义函数时,需要实现相应的转换操作,以及确定第三个参数(目标序列存储器)的类型。以下是一个将浮点数圆整为整数的示例:

#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
int round_to_int(double x) 
{
    return static_cast<int>(std::round(x));
}
int main()
{
    std::vector<double> v{1.0, 2.2, 3.5, 4.7, 9.0}; 
    std::vector<int> result(v.size()); 
    std::transform(v.begin(), v.end(), result.begin(), round_to_int); 
    // result: [1, 2, 4, 5, 9]
    for(auto i : result) { 
        std::cout << i << " "; 
    } 
    std::cout << std::endl; 
    return 0; 
}

在本例中,我们向transform函数传递了一个指向转换函数round_to_int的指针。函数round_to_int接收一个浮点数,将其四舍五入,返回相应的整数。函数指针作为操作函数的参数。元素被取自v序列,存储在result序列中。根据操作的特点以及需要的结果类型,我们选择了使用int类型的序列作为结果序列存储器。

四、transform与多个容器:

最后,transform函数可以处理多个容器。如果提供了多个源和目标序列,则在指定操作函数时应该使用并置二元函数。此时传递的函数接受两个参数,分别是容器中的对应元素,而不是像unary_function接受的单个值。下面是一个使用二进制函数操作两个向量的简单示例:

#include <iostream>
#include <vector>
#include <algorithm>
int sum(int x, int y)
{
    return x + y;
}
int main()
{
    std::vector<int> v1 { 1, 2, 3, 4, 5 };
    std::vector<int> v2 { 1, 1, 2, 2, 3 };
    std::vector<int> result(v2.size()); 
    std::transform(v1.begin(), v1.end(), v2.begin(), result.begin(), sum); 
    for(auto i : result) { 
        std::cout << i << " "; 
    } 
    std::cout << std::endl; 
    return 0; 
}

在这个例子中,我们有两个容器v1和v2分别包含整数的元素,在transform函数中传递了一个求和函数,将结果存储在相应位置的另一个容器中。在函数sum中,我们将两个相对应的参数相加并返回结果。最后的结果是result = [2, 3, 5, 6, 8]

总结:

本文介绍了C++标准库中的一个非常实用的算法——transform函数。我们详细讨论了transform函数的相关应用,包括使用lambda表达式和自定义函数完成转换任务,以及如何操作多个容器。类似于lambda表达式的功能,transform函数使代码变得更短、更清晰,可读性更高。通过更深入地学习及实践,transform函数可以帮助开发者提高工作效率,使代码量更少但实现同样的功能。