I have a vector of doubles, that I want to transform by multiplying by a double. I have it in mind to use std::transform, but I am having trouble working it out. How would I setup up a function to use my "factor" below to transform my init vector to my results vector?
Here is a representation of my code:
double a, b, factor;
std::vector<double> init;
std::vector<double> result;
// Code that initializes a, b, and
// fills in InitVec with timeseries (type double) data
factor = a/b;
result.resize(init.size())
std::transform(init.begin(), init.end(), result.begin(), /*function that multiplies init by factor*/)
is it as simple as:
std::transform(init.begin(), init.end(), result.begin(), *factor)
Thanks.
There are at least three different ways you can do this, including:
custom functor class
lamba instance
bound binary functor
See below for all three:
#include <iostream>
#include <algorithm>
#include <vector>
struct mult_by
{
double val;
mult_by(double v) : val(v) {}
double operator()(double arg) { return arg * val; };
};
int main()
{
using namespace std::placeholders;
double a = 1, b = 2, factor = a/b;
std::vector<double> init;
std::vector<double> result;
init.emplace_back(1.0);
init.emplace_back(2.0);
// using a functor
std::transform(init.begin(), init.end(), std::back_inserter(result), mult_by(factor));
// using a lambda
std::transform(init.begin(), init.end(), std::back_inserter(result),
[factor](double d){ return d * factor; });
// binding to a standard binary-op (std::multiplies)
std::transform(init.begin(), init.end(), std::back_inserter(result),
std::bind(std::multiplies<double>(), _1, factor));
// should report three pairs of 0.5 and 1
for (auto x : result)
std::cout << x << '\n';
}
Which you choose depends on preference or compiler limitations. Personally I would find the latter distasteful, but presented it as an option just because it is possible. I purposely left out std::for_each and outright hand-looped implementations, as those don't appear to be what you're looking for.
Best of luck.
You need a function which gets a double and returns a new double.
And you need to get factor in this function too.
Easy with a lambda expression:
std::transform(init.begin(), init.end(), result.begin(),
[factor](double val) -> double { return val*factor; }
);
To understand it better, it is a short version for the following code, except factor can be used in the function even if it is just a local variable where transform is called:
double modify(double val)
{
return val*factor;
}
...
std::transform(init.begin(), init.end(), result.begin(), modify);
Ie. a lambda expression is a unnamed function written inline as part of other stuff, and it can "capture" local variables from it´s caller context too.
Related
I have a vector of complex numbers and I need to sort them by their argument. Sadly, the numbers have type complex<int>, so function arg(c) returns an integer in range [-3,3] instead of a float and the numbers can't be sorted properly.
I've tried also
typedef complex<int> ci;
typedef complex<double> cd;
vector<ci> a;
sort(a.begin(), a.end(), [](ci v, ci u) { return arg(cd(v)) < arg(cd(u)); });
but it does not work either (compilation error: no matching function for call to ‘std::complex<double>::complex(ci&)).
Can I sort these numbers without changing their type?
You get the error because there is no converting constructor from std::complex<int> to std::complex<double> you have to construct the std::complex<double> by passing real and imaginary parts to the constructor:
#include <vector>
#include <complex>
#include <algorithm>
int main() {
std::vector<std::complex<int>> a;
std::sort(a.begin(), a.end(), [](const auto& v,const auto& u) {
return std::arg(std::complex<double>(v.real(),v.imag())) < std::arg(std::complex<double>(u.real(),u.imag()));
});
}
Note that you can also use atan2 directly without constructing the std::complex<double> as mentioned by user17732522.
Last but not least, reconsider if you really need int with std::complex. From cppreference:
T - the type of the real and imaginary components. The behavior is unspecified (and may fail to compile) if T is not float, double, or long double and undefined if T is not NumericType.
Basically this means that you need to check the implementation you are using whether it supports std::complex<int> at all.
I want to multiply and divide all the elements of std::vector by constant in the same way as it is performed in C++ for ordinary types: at least the result should be integer when input vector has integer type and floating-point type otherwise.
I have found the code for multiplication based on std::multiplies and modified it with the replacement std::divides. As the result, the code works but not in the order I want it:
#include <iostream>
#include <vector>
#include <algorithm>
// std::vector multiplication by constant
// http://codereview.stackexchange.com/questions/77546
template <class T, class Q>
std::vector <T> operator*(const Q c, const std::vector<T> &A) {
std::vector <T> R(A.size());
std::transform(A.begin(), A.end(), R.begin(),
std::bind1st(std::multiplies<T>(),c));
return R;
}
// My modification for division. There should be integer division
template <class T, class Q>
std::vector <T> operator/(const std::vector<T> &A, const Q c) {
std::vector <T> R(A.size());
std::transform(A.begin(), A.end(), R.begin(),
std::bind1st(std::divides<T>(),c));
return R;
}
int main() {
std::vector<size_t> vec;
vec.push_back(100);
int d = 50;
std::vector<size_t> vec2 = d*vec;
std::vector<size_t> vec3 = vec/d;
std::cout<<vec[0]<<" "<<vec2[0]<<" "<<vec3[0]<<std::endl;
// The result is:
// 100 5000 0
size_t check = vec[0]/50;
std::cout<<check<<std::endl;
// Here the result is 2
// But
std::vector<double> vec_d;
vec_d.push_back(100.0);
vec_d = vec_d/50;
std::cout<<vec_d[0]<<std::endl;
// And here the result is 0.5
return 0;
}
How can I write my operator correctly ? I thought that std::bind1st would call division by c for each element, but it does the opposite somehow.
EDIT: I understand that I can write a loop, but I want to do a lot of divisions for big numbers, so I wanted it to be faster...
Using std::transform with C++11, I'd suggest making a lambda (see this tutorial) instead of using bind:
std::transform(A.begin(), A.end(), R.begin(), [c](T val) {
return val / c;
});
In my opinion, lambdas are almost always more readable than binding, especially when (like in your case) you're not binding all of the function's parameters.
Although if you're worried about performance, a raw for loop might be slightly faster, as there's no overhead of the function call and creating the lambda object.
According to Dietmar Kühl:
std::transform() may do a bit of "magic" and actually perform better than a loop. For example, the implementation may choose to vectorize the loop when it notices that it is used on a contiguous sequence of integers. It is, however, rather unlikely to be slower than the loop.
auto c_inverse= 1/c;
std::transform(A.begin(), A.end(), R.begin(), [c_inverse](T val) {
return val * c_inverse;
});
Similar to the other post, but it should be mentioned that rather than division, you will most likely see performance gains by multiplying by the inverse.
Why make it only for vectors? Here's a way to make more generic, to work with many types of containers:
template <class container, class Q>
container operator/(const container& A, const Q c) {
container R;
std::transform(std::cbegin(A), std::cend(A), std::back_inserter(R),
[c](const auto& val) {return val / c; });
return R;
}
Sure, it is expected to be a bit slower than with pre-allocation for a vector, since the back_inserter will allocate dynamically as it grows, but well, sometimes it might be appropriate to trade speed for genericity.
I have a C++ application with a struct which looks like:
struct test_struc {
std::string name;
int x;
int y;
std::vector<int> data;
};
And I would like to transform two std::vector<test_struc> using the lines according to their data element in the structure. So far, I have the code:
std::vector<test_struc> first = <from somewhere else>;
std::vector<test_struc> second = <from somewhere else>;
std::vector<int> result;
std::transform (second.begin(), second.end(), first.begin(), result.begin(), op_xor);
where op_xor is:
int op_xor (int &i,
int &j) {
return i^j;
}
This works well if first and second are vectors of int, but since they are not, I don't know how to tell the code to use the data element of test_struc as arguments to std::transform.
Am I barking up the wrong tree? Or is there a way to do this?
Note that at least with a modern compiler, you probably want to implement the operation as a lambda expression, so it would look something like:
std::transform(second.begin(), second.end(),
first.begin(),
std::back_inserter(result),
[](test_struct const &a, test_struct const &b) {
return a.y ^ b.y;
});
Minor aside: as it was, you had UB, trying to write through result.begin() when the size of result was 0. You could either use back_inserter as above, or you could define result initializing its size to second.size().
Your binary functor must take two test_structs:
int op_xor (const test_struct& i,
const test_struct& j)
{
return 42; // replace wit your desired logic.
}
It isn't clear what exactly you want the functor to do, but it should operate on the test_structs and return an int.
Or use lambdas.
And remember size of other vectors must be the same or more than "second"
result.resize(second.size());
std::transform(second.begin(), second.end(), first.begin(), result.begin(),
[](test_struct & one, test_struct & two){ return one.x ^ two.x; });
But Jerry's example with back_inserter is better
Also you can do it using boost::transform and boost phoenix lambdas:
#include <boost/range/algorithm.hpp>
#include <boost/phoenix.hpp>
using boost::phoenix::arg_names::arg1;
using boost::phoenix::arg_names::arg2;
boost::transform(second, first, std::back_inserter(result), (&arg1)->*&test_struc::x ^ (&arg2)->*&test_struc::x);
First and second arguments of boost::transform are ranges, so you do not have to write second.begin(), second.end(), first.begin() here.
I am trying to perform a transform reduce on a vector of structs. The struct contains two numbers. I want the unary function to do something with these two numbers and return a single value for each struct in my vector and reduce with a summation of these values. How do I write my functor to access the values in the struct?
for example, whats the proper syntax for mystruct.value1 within the function?:
struct unary_op
{
float operator()()
{
return mystruct.value1 + mystruct.value2; //function is a lot more complex
}
}
so I can do:
unary_op uop1;
thrust::transform_reduce(myvec.begin(), myvec.end(), uop1, 0, thrust::add)
Disclaimer:
Since you obviously did not post real code and your example looks like a few unrelated code lines, my answer might not be what you are looking for - a SSCCE would have been nice.
If I understand correctly, you want to transform_reduce a vector of MyStructs to the sum of all the structs member values. To do that, you need the binary addition (thrust::add) and a unary op taking a MyStruct and returning the addition of its member values:
struct MyStruct {
float value1;
float value2;
};
std::vector<MyStruct> myvec;
/* fill myvec */
//C++11 with lambdas:
auto result = thrust::transform_reduce(begin(myvec), end(myvec),
[](MyStruct const& ms) { //unary op for transform
return ms.value1 + ms.value2;
},
0, thrust::add);
//C++03 with a functor:
struct MyStructReducer {
float operator()(MyStruct const& ms) {
return ms.value1 + ms.value2;
}
};
float result = thrust::transform_reduce(myvec.begin, myvec.end(),
MyStructReducer(), 0, thrust::add);
You could as well use a free function instead of the Reducer class.
//C++03 with a function:
float reduceMyStruct(MyStruct const& ms) {
return ms.value1 + ms.value2;
}
/* ... */
float result = thrust::transform_reduce(myvec.begin, myvec.end(),
reduceMyStruct, 0, thrust::add);
HTH
Hi I want to (multiply,add,etc) vector by scalar value for example myv1 * 3 , I know I can do a function with a forloop , but is there a way of doing this using STL function? Something like the {Algorithm.h :: transform function }?
Yes, using std::transform:
std::transform(myv1.begin(), myv1.end(), myv1.begin(),
std::bind(std::multiplies<T>(), std::placeholders::_1, 3));
Before C++17 you could use std::bind1st(), which was deprecated in C++11.
std::transform(myv1.begin(), myv1.end(), myv1.begin(),
std::bind1st(std::multiplies<T>(), 3));
For the placeholders;
#include <functional>
If you can use a valarray instead of a vector, it has builtin operators for doing a scalar multiplication.
v *= 3;
If you have to use a vector, you can indeed use transform to do the job:
transform(v.begin(), v.end(), v.begin(), _1 * 3);
(assuming you have something similar to Boost.Lambda that allows you to easily create anonymous function objects like _1 * 3 :-P)
Modern C++ solution for your question.
#include <algorithm>
#include <vector>
std::vector<double> myarray;
double myconstant{3.3};
std::transform(myarray.begin(), myarray.end(), myarray.begin(), [&myconstant](auto& c){return c*myconstant;});
I think for_each is very apt when you want to traverse a vector and manipulate each element according to some pattern, in this case a simple lambda would suffice:
std::for_each(myv1.begin(), mtv1.end(), [](int &el){el *= 3; });
note that any variable you want to capture for the lambda function to use (say that you e.g. wanted to multiply with some predetermined scalar), goes into the bracket as a reference.
If you had to store the results in a new vector, then you could use the std::transform() from the <algorithm> header:
#include <algorithm>
#include <vector>
int main() {
const double scale = 2;
std::vector<double> vec_input{1, 2, 3};
std::vector<double> vec_output(3); // a vector of 3 elements, Initialized to zero
// ~~~
std::transform(vec_input.begin(), vec_input.end(), vec_output.begin(),
[&scale](double element) { return element *= scale; });
// ~~~
return 0;
}
So, what we are saying here is,
take the values (elements) of vec_input starting from the beginning (vec_input.begin()) to the end (vec_input.begin()),
essentially, with the first two arguments, you specify a range of elements ([beginning, end)) to transform,
range
pass each element to the last argument, lambda expression,
take the output of lambda expression and put it in the vec_output starting from the beginning (vec_output.begin()).
the third argument is to specify the beginning of the destination vector.
The lambda expression
captures the value of scale factor ([&scale]) from outside by reference,
takes as its input a vector element of type double (passed to it by std::transform())
in the body of the function, it returns the final result,
which, as I mentioned above, will be consequently stored in the vec_input.
Final note: Although unnecessary, you could pass lambda expression per below:
[&scale](double element) -> double { return element *= scale; }
It explicitly states that the output of the lambda expression is a double. However, we can omit that, because the compiler, in this case, can deduce the return type by itself.
I know this not STL as you want, but it is something you can adapt as different needs arise.
Below is a template you can use to calculate; 'func' would be the function you want to do: multiply, add, and so on; 'parm' is the second parameter to the 'func'. You can easily extend this to take different func's with more parms of varied types.
template<typename _ITStart, typename _ITEnd, typename _Func , typename _Value >
_ITStart xform(_ITStart its, _ITEnd ite, _Func func, _Value parm)
{
while (its != ite) { *its = func(*its, parm); its++; }
return its;
}
...
int mul(int a, int b) { return a*b; }
vector< int > v;
xform(v.begin(), v.end(), mul, 3); /* will multiply each element of v by 3 */
Also, this is not a 'safe' function, you must do type/value-checking etc. before you use it.