繁体   English   中英

std :: transform用两个std :: vector和一个常量作为参数

[英]std::transform with two std::vector and one constant as arguments

我想使用std :: transform来做类似于binary_op但有一个额外的常量,例如,得到两个向量的乘积:x1 =(10,20,30,40,50)和x2 =(2, 4,6,8,10),我们可以写:

#include <iostream>
#include <algorithm>
#include <vector>


double multiply(double x, double y){
    return x*y;
}

int main () {
  std::vector<int> x1;
  std::vector<int> x2;


  for (int i=1; i<6; i++)
    x1.push_back (i*10); //10,20,30,40,50

  for (int i=1; i<6; i++)
    x2.push_back (i*2);  //2,4,6,8,10



  std::transform (x1.begin(), x1.end(), x2.begin(), x1.begin(),multiply);


  for (std::vector<int>::iterator it=x1.begin(); it!=x1.end(); ++it)
    std::cout << ' ' << *it;
  //output: 20,80,180,320,500

  return 0;
}

上面的代码将元素乘以x1和x2并返回(20,80,180,320,500)。

但是,如果我想计算x1 $ \\ dot $ x2 + c,其中c是标量常量,如1,如下面的函数:

double multiply(double x, double y, double c){
    return x*y + c;
}

在这种情况下,我如何使用std :: transform应用于两个向量x1和x2? 我是否必须使标量常数c成为具有相同元素的向量,如(c,c,c ... c)?

提前致谢。

试试这个

int c = 20;
std::transform (x1.begin(), x1.end(), x2.begin(), x1.begin(),[&c](auto i, auto j) { return  multiply(i,j) + c ; });

它是lambda函数; i是来自x1的元素,j是来自x2的元素。 [&]通过引用信号捕获在lambda外定义的所有值。

您可以通过提供一个仿函数来实现这一点,即一个具有调用操作符的结构,它可以执行您想要的操作。 执行此操作的旧方法是执行以下操作:

struct MultWithConstantAdder {
   const double adder;
   MultWithConstantAdder(double adder): adder(adder) {}
   double operator()(double x, double y) { return add(x,y,adder); }
};
// ... rest of your code
std::transform(x1.begin(), x2.end(), x2.begin(), x1.begin(), MultWithConstantAdder(someConstantThatYouWant));

C ++ 11添加了lambdas,它允许您在不必在代码的其他部分中定义结构的情况下执行此操作:

std::transform(x1.begin(), x2.end(), x2.begin(), x1.begin(),
  [](double x, double y) { return add(x,y, someConstant); });

如果你不习惯它,语法可能看起来有点时髦,但这基本上和上面的东西一样。

lambda中的[]部分确定外部范围的哪些部分(即不在lambda本身中的所有部分)应该是可见的。 []表示无, [=]表示按值复制的所有内容, [&]表示通过引用可见的所有内容。 你也可以直接命名,所以例如[someConstant, &someOtherConstant]将通过值捕获someConstant而通过引用捕获someOtherConstant

你甚至不需要multiply(double x, double y)函数。 使用简单的lambda,您可以完成所需的所有乘法和加法。

int c = 2;
std::transform (x1.begin(), x1.end(), x2.begin(), x1.begin(),
[&c](const auto& x1_ele, const auto& x2_ele){ return (x1_ele*x2_ele) + c;  });

我不确定,这是一个处理std::transform的完美案例,因为你可以使用更简单的std::for_each来实现同样的目标。 但是需要额外的变量( index )。

int index = 0;
int c = 2;
std::for_each(x1.begin(), x1.end(), [&](auto& x1_ele){ x1_ele = (x1_ele*x2[index]) + c; ++index; });

来自cppreference.com

std::transform不保证unary_op或binary_op的有序应用。 要按顺序将函数应用于序列或应用修改序列元素的函数,请使用std::for_each

你可以捕获lambda中的标量:

double c = 1
std::transform (x1.begin(), x1.end(), x2.begin(), x1.begin(), [c]
    (double x, double y){
       return x*y + c;
    });

你为什么不使用std::bind

例如:

#include <functional>

using namespace std;
using namespace std::placeholders;

double multiply(double x, double y, double c){
    return x*y + c;
}

//in main()
  //scallar is 10.0 in this case --> last parameter.
  auto multiplyScalar = bind(&multiply, _1, _2, 10.0);

  transform(x1.begin(), x1.end(), x2.begin(), x1.begin(), multiplyScalar);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM