I'm sorry if this is a stupid question but I'm a bit of a c++ noob and I haven't been able to find the answer. I'm working with boost multi_array, and I'm trying to do something like this:
typedef boost::multi_array<double,2> array2D;
typedef array2D::array_view<1>::type array2Drow;
typedef boost::multi_array_types::index_range range;
...
array2D A = ... (2-d array) ...;
array2Drow X = A(boost::indices[0][range()]);
...
returnVal1 = f(X);
returnVal2 = f(X+0.1*X);
returnVal3 = f(X-0.1*X);
I was trying to use std::transform for this; I understand I can write some sort of functor (call it "op") that multiplies X by 0.1 and adds/subtracts the result from X, but this is where I run into trouble--I don't know what to put in place of the ???:
returnVal1 = f(X);
returnVal2 = f(transform(X.begin(),X.end(),???,op(0.1,X)));
returnVal3 = f(transform(X.begin(),X.end(),???,op(-0.1,X)));
Is there a way to do this without defining an intermediate object that then gets passed to f? Thanks in advance!
If your function f takes a container, then you will have to create a container with the transformed values. In your example you seem to also expect that X remains unchanged by the first transformation, so you you cannot just modify it inplace
returnVal1 = f( X );
transform( X.begin(), X.end(), X.begin(),
[]( double val ){ return val + 0.1*val; } );
returnVal2 = f( X );
If you don't want to create explicit local temporaries then you can construct them using a helper function.
// pass in by value to get a copy, modify it inplace and return it
array2Drow transformed( array2Drow copy, double factor )
{
std::transform( copy.begin(), copy.end(), copy.begin(),
[&]( double val ){ return val + factor*val; } ) );
return copy;
}
The calculation of the return values can then be written using the helper.
returnVal1 = f( X );
returnVal2 = f( transformed( X, 0.1 ) );
returnVal3 = f( transformed( X, -0.1 ) );
The ??? needs to be an iterator for a container where you want to store the result of the transform operation, i.e. the return value of op
However, your idea is wrong.
std::transform returns (see http://en.cppreference.com/w/cpp/algorithm/transform)
Return value
Output iterator to the element past the last element transformed.
It makes no sense to pass that iterator to a function as it is end of the container.
Further, the signature of op doesn't fulfil the requirements for std::transform.
If f expects to receive a array2Drow, then you need to pass it one (containing the correct data).
With that given, you really only have a couple of choices: either modify the data in the existing collection (and repeatedly pass the same collection), or else create a new collection each time you invoke it.
If f really only needs one of the items at a time (e.g., like an accumulator), then you may be able to rewrite f to only take one input at a time, then at the end of each "run", retrieve the value and reset the accumulator.
In that case, you can probably create an iterator type that will invoke the accumulator for each item as its created, and pass an instance of that accumulator to std::transform as the destination where the result should be written.
For reference, you may want to look at Boost Accumulators.
Related
I have:
vector<double> ved1 = { 1,2,3,4,5,6,7,8,9,10 };
vector<double> ved2 = { 11,12,13,14,15,16,17,18,19,20 };
vector<double> ved3(10);
and I want to have ved3=ved3/2 but I can't get it correctly, the result is 2/ved3;
How to use divides?
transform(ved1.begin(), ved1.end(), ved2.begin(), ved3.begin(), plus<double>());
transform(ved3.begin(), ved3.end(), ved3.begin(), bind1st(divides<double>(),2));`
I want cos(ved2), but I cannot get it. What's wrong with my code?
double cos_1(double x) { return cos(x); }
for_each(ved2.begin(), ved2.end(), cos_1);
bind1st will bind 2 to the 1st argument of divides, and then transform will supply each element of ved3 to divides as the second argument. So the result will be divides(2, ved3[0]), divides(2, ved3[1]) and so on.
If you want to calculate divides(ved3[...], 2) instead, use bind2nd(divides<double>(), 2). This way, 2 will be bound to the second argument, leaving the first one vacant for transform.
How to use std::for_each to apply a cosine elementwise
std::for_each does not fill some output; or necessarily change the input container/range. It just applies an invocable object to each element of a range. If the function has no "side effects" - than the for_each would be useless. Specifically, in your case - you're computing the cosine of each value, but not doing anything with it.
If you want to change the values in-place, you'll need to specifically do that:
void apply_cos(double& x) { x = std::cos(x); }
// ...
for_each(ved2.begin(), ved2.end(), apply_cos);
or using a lambda expression:
for_each(ved2.begin(), ved2.end(), [](double& x) { x = cos(x); });
Note the use of a reference input to the function rather than a value: double& x, not double x. That means that when you change x in apply_cos(), the value in the input range to std::for_each changes.
The following function is supposed to take the coefficients of a polynomial and create a function of time from them:
std::function<double(double)> to_equation(const std::vector<double>& coefficients)
{
return [coefficients](double t)
{
auto total = 0.0;
for (int i = 0; i < coefficients.size(); i++)
{
total += coefficients[i] * pow(t,i);
return total;
}
};
}
It should be usable as follows:
std::vector<double> coefficients = {1.0,2.0,3.0};
auto f = to_equation(coefficients);
auto value = f(t);
The code does however not work as intended, since at the time of execution of f(t), not the coefficients passed to to_equation(coefficients) are used, but some totally different values magically captured from the context. What is happening and how can I fix that?
Well, you are returning a lambda that capture coefficients by value. If you pass some vector to the to_equation function, all values will be copied, and the lambda won't refer to the original vector anymore.
I suggest this solution:
// auto is faster than std::function
auto to_equation(const std::vector<double>& coefficients)
{
// Here, you capture by reference.
// The lambda will use the vector passed in coefficients
return [&coefficients](double t)
{
// ...
};
}
However, you must sometime deal with code like this:
std::function<double(double)> f;
{
std::vector<double> coeff{0.2, 0.4, 9.8};
f = to_equation(coeff);
}
auto result = f(3);
This is bad, the vector coeff don't live long enough, and we refer to it after the vector is destroyed.
I suggest adding this overload to your function:
// when a vector is moved into coefficients, move it to the lambda
auto to_equation(std::vector<double>&& coefficients)
{
// Here, you capture by value.
// The lambda will use it's own copy.
return [coeff = std::move(coefficients)](double t)
{
// ...
};
}
Then, calling your function is possible in both ways:
std::vector<double> coeff{0.2, 0.4, 9.8};
auto f1 = to_equation(coeff); // uses reference to coeff
auto f2 = to_equation({0.2, 0.4, 9.8}) // uses value moved into the lambda
You can capture by reference, instead of by value. But, of course, if the underlying vector goes out of scope and gets destroyed before the lambda gets invoked, you'll have a big mess on your hands.
The safest course of action is to use a std::shared_ptr<std::vector<double>> instead of a plain vector, and capture that by value. Then, the lambda will always, essentially, feed on whatever were the most recent set of coefficients, and won't blow up if it gets called after all other references to the underlying vector, from whatever code computed them, go out of scope.
(Of course, you have to keep in mind what's going to happen here if the lambda gets copied around, since all copies of the original lambda will be using the same vector).
For more information, open the chapter of your C++ book that explains the difference between capturing by value and by reference, when using lambdas.
So I was trying to find the average of all the values to the left and right of the iterator into a new vector. I was thinking of something like :
transform(begin(vector1)+1,end(vector2)-1, back_inserter
(vector2),[](vector<int>::iterator n) {return (*(n - 1) + *(n) + *
(n+1))/3;});
Unfortunately this gives me an error about convert argument from 1 'int'
to std::vector_iterator
I'm declaring the parameter as a vector iterator, but I must be doing something wrong. I need to do this in either lambda or in using something in functional. I would like a point in the right direction of how to do this at the very least, since it's a pain to try and search the answer for this. Maybe if this has been asked before you can teach me what to type in to find an answer like this.
The argument should be the vector's value_type (or convertible to it, like const reference), so it should be int.
std::transform is rather limited, in that it is designed to
implement a bijection—a simple one-to-one translation.
The function will be called with exactly one argument, the value
currently under the iterator, and must always return exactly one
element.
It is possible for the functional object to have state, but you
have to be careful, since it has value semantics, and can and
will be copied. You might try something like this, however:
class Smoother
{
std::vector<int>* m_previous;
public:
Smoother( std::vector<int>& previous )
: m_previous( previous )
{
}
int operator()( int next )
{
int results = std::accumulate( m_previous->begin(), m_previous->end(), next ) / (m_previous->size() + 1);
m_previous->erase( m_previous->begin() );
m_previous->push_back( next );
return retval;
}
};
You then first initialize a vector with the starter values,
something like:
std::vector<int> tmp( vector1.begin(), vector1.begin() + 2 );
std::transform( vector1.begin() + 2, vector1.end(), std::back_inserter( vector2 ), Smoother( tmp ) );
Obviously, something like Smoother could be a template, and you could wrap the whole thing nicely in a function. (And even more obviously, if you did so, you'd want a bit more error checking.)
I want to know how I can define vector variables to save output of this code in vector?
/*what should be here?*/=agent.GetInfoState().GetPositionInfo().GetCloseTeammateToTeammate(2);
GetcloseTeammateToTeammate is defined as:
const std::vector<Unum> & GetCloseTeammateToTeammate(Unum i)
{
Assert(i > 0); return GetCloseTeammateToPlayer(i); }
GetCloseTeammateToTeammate returns a reference to a constant vector.
Simply use:
const std::vector<Unum>& x = agent.GetInfoState().GetPositionInfo().GetCloseTeammateToTeammate(2);
to get the reference. Note that you can only call const member functions of vector.
To get a copy of the vector, do:
std::vector<Unum> x = agent.GetInfoState().GetPositionInfo().GetCloseTeammateToTeammate(2);
Only copy if you really need to.
I must be missing something here. Is it not simply this:
const std::vector<Unum> &my_vector = agent.GetInfoState().GetPositionInfo().GetCloseTeammateToTeammate(2);
There are two different options there, depending on what you actually want. If you only intend to do some processing on the given vector in the short term, (and assuming single threaded execution and a couple other considerations) you can just keep the reference:
std::vector<Unum> const & v = agent.GetInfoState().GetPositionInfo().GetCloseTeammateToTeammate(2);
for ( std::vector<Unum>::const_iterator it = v.begin(), end = v.end(); it != end; ++it )
{
// do something
}
If what you want is to save a copy of the vector so that at a later time you can check for changes, or you want to use the vector as it is now without any later changes (note that this is not entailing thread safety!), just copy it:
std::vector<Unum> copy = agent.GetInfoState().GetPositionInfo().GetCloseTeammateToTeammate(2);
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.