I have got a std::vector X of std::vector of, say, double in C++.
How can I transform X into a std::vector Y of int such that X[i].size() == Y[i] holds for all admissible indices i?
std::vector< std::vector<int> > X;
...
/* What I want to do should look as follows */
std::vector<int> Y = std::copy_and_transform( X, lambda_to_get_size );
Of course, this can be realized with a loop, but in C++11 we would like to use lambdas instead. I have not found anything like that in std::algorithm. The standard tools seem to only give in place transformations that change the original vector and which do not allow changing the data type.
You can use std::transform:
std::vector<int> Y;
std::transform(X.cbegin(), X.cend(), std::back_inserter(Y), [](const std::vector<int>& value) {
return value.size();
});
Related
I have a function which calculates the first derivative dy/dx for discrete values y(x) stroed as std::vector:
vector<double> CalcDerivative(vector<double>&y, vector<double>&x) {...}
Often the spacing dx is constant so it would be more efficient to pass a double to this function instead of vector<double> as argument x.
I tried to accomplish this with std::variant. The drawback with std::variant is however, that it cannot handle references so the vector x has to be copied while being passed as a variant to the function.
For now I solved the problem by defining two functions with overloaded arguments. But I wonder whether there is a more elegant solution which won't duplicate the code for the two cases (x as double or as vector<double>).
One possible solution might be to define the "worker" function such that it is independent of the "number of passed doubles". For this purpose, std::span is suitable. The exemplary solution might look like:
std::vector<double> CalcDWorker(
std::span<const double> y, std::span<const double> x)
{
... // x.size() == 1 indicates uniform spacing
}
std::vector<double> CalcDerivative(
const std::vector<double>& y, const std::vector<double>& x)
{
return CaclDWorker({y.begin(), y.end()}, {x.begin(), x.end()});
}
std::vector<double> CalcDerivative(
const std::vector<double>& y, double x)
{
return CaclDWorker({y.begin(), y.end()}, {&x, 1});
}
It requires C++20, but there are third-party span implementations available also for earlier C++ versions (such as the one provided by Boost).
Live demo: https://godbolt.org/z/n6adEKWes
x is an unsigned integer. Runtime-wise, what's the fastest and most elegant way to declare a container/initializer list filled with unsigned integers from 0 to x?
Ideally I'd like the solution to be a one-liner, something along the line of:
std::vector<int> v = {0..x};
This is what I have so far, but I'm not sure about the performance:
std::vector<int> v(x);
std::generate_n(v.begin(), x, [] { static int i = -1; ++i; return i;});
Since C++11, there is a function in the C++ standard library that is made specifically for this: std::iota
This is a piece of code I'm currently using and I was wondering if there was a more elegant way of doing this in C++11 -
Essentially vector_a is copied to vector_b, then slightly modified, then vector_b is returned.
Vector elements are of class Point which is basically (leaving out constructors and a bunch of methods):
class Point {
double x,
y,
z;
};
Ideally I'd love to boil down the assignment of member z from vector_a to vector_b to something like a line or two but couldn't come up with an elegant way of doing it.
Any suggestions welcome!
auto localIter = vector_a.begin();
auto outIter = vector_b.begin();
while (localIter != vector_a.end() && outIter != vector_b.end())
{
outIter->z = localIter->z;
localIter++;
outIter++;
}
You may use transform().
std::transform (vector_a.begin(), vector_a.end(), vector_b.begin(), vector_a.begin(), [](Elem a, Elem b) { a->z = b->z; return a; });
Where Elem is a type of vector element.
As the vector has a random access iterator (using of std::next is effective) then I would write the code the following way
auto it = vector_a.begin();
std::for_each( vector_b.begin(),
std::next( vector_b.begin(),
std::min( vector_a.size(), vector_b.size() ) ),
[&it] ( Point &p ) { p.z = it++->z; } );
A partial copy is, actually, just a transformation of the elements (one of many), and therefore std::transform is a natural fit here.
Like many algorithms acting on multiple sequences, you have to be careful about the bounds of your containers; in this particular case, since vector_b just receives stuff, the easiest is to start empty and adjust its size as you go.
Thus, in the end, we get:
vector_b.clear();
std::transform(vector_a.begin(),
vector_a.end(),
std::back_inserter(vector_b),
[](Elem const& a) { Elem b; b.z = a.z; return b; });
transform is perhaps the most generic algorithm in the Standard Library (it could imitate copy for example), so you should carefully consider whereas a more specialized algorithm exists before reaching for it. In this case, however, it just fits.
I would be tempted to do something a bit like this:
#include <vector>
struct info
{
int z;
};
int main()
{
std::vector<info> a = {{1}, {2}, {3}};
std::vector<info> b = {{4}, {5}};
for(size_t i(0); i < a.size() && i < b.size(); ++i)
b[i].z = a[i].z;
}
I have a simple point structure
struct mypoint
{
int x;
int y;
};
and a vector of mypoints
vector<mypoint> myvector;
If I want to create a vector of int containing all the coordinates of my points (i.e. x1, y1, x2, y2, x3, y3, ...), I could easily do it in the following way
vector<mypoint>::iterator pt, ptend(myvector.end());
vector<int> newvector;
for(pt=myvector.begin(); pt!=ptend; ++pt)
{
newvector.push_back(pt->x);
newvector.push_back(pt->y);
}
Is there a way to obtain the same result in one (or two) line(s) of code using the C++11?
std::vector<int> extractIntsFromPoints(const std::vector<mypoint>& pointVector)
{
std::vector<int> retVector;
for (const auto& element : pointVector)
{
retVector.push_back(element.x);
retVector.push_back(element.y);
}
return retVector;
}
Call this function where you need the int vector.
I threw in the range-based for loop to make it extra C++11.
Since you're using C++11, you can use the new for syntax.
vector<int> newvector;
for( const auto &pt : myvector)
{
newvector.push_back(pt.x);
newvector.push_back(pt.y);
}
steal from the post: C++ std::transform vector of pairs->first to new vector
vector<int> items;
std::transform(pairs.begin(),
pairs.end(),
std::back_inserter(items),
[](const std::pair<int, int>& p) { return p.first; });
Here's about 4 lines, using a lambda:
vector<mypoint> points;
vector<int> iv;
points.push_back(mypoint(1,2));
points.push_back(mypoint(3,4));
points.push_back(mypoint(5,6));
for_each(points.cbegin(), points.cend(),
[&iv](const mypoint &pt) {
iv.push_back(pt.x);
iv.push_back(pt.y);
});
You could use a std::pair<> in which you push the coordinates using std::make_pair and then push the std::pair<> into the vector such as:
mypoint a_point;
std::pair<int, int> point = std::make_pair(a_point.x, a_point.y);
vector<std::pair<int, int>> vec.push_back(point).
Perhaps bulky but in two lines it works well and encapsulates a point rather than separating the magnitudes of each point axis and placing them inside a std::vector.
As reima already noted, if you only want to reference the existing sequence, it is sufficient to cast myvector.data() to int* (assuming sizeof(mypoint) == 2 * sizeof(int) holds).
However, if you explicitly want a copy of the flattened sequence, you are probably better off creating a small utility function like this:
template <typename T, typename U>
std::vector<T> flatten(std::vector<U> const& other) {
static_assert(std::is_trivially_copyable<U>::value,
"source type must be trivially copyable!");
static_assert(std::is_trivially_copy_constructible<T>::value,
"destination type must be trivially copy constructible!");
static_assert((sizeof(U) / sizeof(T)) * sizeof(T) == sizeof(U),
"sizeof(U) must be a multiple of sizeof(T)!");
return std::vector<T>(reinterpret_cast<T const*>(other.data()),
reinterpret_cast<T const*>(std::next(other.data(), other.size())));
}
template <typename U>
std::vector<typename U::value_type> flatten(std::vector<U> const& other) {
return flatten<typename U::value_type>(other);
}
reducing your code to
auto newvector = flatten<int>(myvector);
or - if you equip your mypoint struct with a (STL-conforming) value_type member type - even to
auto newvector = flatten(myvector);
Note, that this utility function is nothing more than a tweaked constructor using the inherently unsafe reinterpret_cast to convert mypoint pointers into int pointers.
To get rid of the safety caveats that go along with the use of reinterpret_cast, the flatten function uses some static_assert parachutes. So, it's better to hide all this in a seprate function.
Still, it uses a lot of C++11 features like auto, move construction, static_assert, type traits, std::next and vector::data() which pretty much strips down your call site code to a bare minimum.
Also, this is as efficient as it gets because the range constructor of vector will only perform the memory allocation and call uninitialized_copy, which will probably boil down to a call of memcpy for trivially copyable types.
There is a function, accepting 2D-array:
void foo ( double ** p )
{ /*writing some data into p*/ }
I wouldn't like to pass raw 2D array into this function because i don't want to manage memory calling new and delete. Also i wouldn't like to change function signature to void foo ( std::vector< std::vector<double> >& ). And i can't make foo as a template function (in my project it's a COM-interface method).
I would like to pass some RAII object decoring it raw-one, like
void foo ( double * p ){}
std::vectore<double> v(10);
p( &v[0] );
Is there way to do this for 2D-arrays? I tried
std::vector< std::vector<int> > v;
foo( &v[0][0] )
and
std::vector< std::tr1::shared_ptr<int> > v;
but i get compile errors error C2664 - cannot convert parameter.
Also, can one be sure that raw address arithmetics inside the function works ok in this case?
No C++11, the sizes of 2D-array are known.
One possible solution is to change:
std::vector< std::vector<int> > v;
foo( &v[0][0] )
to
std::vector< std::vector<int> > v;
std::vector<int*> v_ptr;
for (...) {
v_ptr[i] = &v[i][0];
}
foo( &v_ptr[0])
Although Andreas already gave an answer to your question that solves your particular problem, I would like to point out, that although that works, it is probably not what you want to do.
As you are using C++ (and not an easier to use language), I am assuming that you care about performance. In that case your approach is in all likelihood wrong from the beginning, as double** represents an array of arrays (or rather can represent) and not a 2D array. Why is this bad? Because, just as with the std::vector< std::vector<int> > example, multiple allocations are required, and the resulting memory is non-contiguous (which is bad for the cache) unlike a double array[N][M].
For 2D arrays you should in fact use 1D arrays with index calculation, which is far more cache-friendly. This of course does not allow [x][y]-style indexing (instead you have to use [x+N*y] or [y+M*x], depending on your choice of "Fortran order" or "C order"), but avoids cache issues and only requires a single allocation (and a simple double*pointer).
If you are iterating all elements of the array as in
for(unsigned x = 0; x < N; ++x) for(unsigned y = 0; y < M; ++y)
{
unsigned idx = y + M * x;
p[idx] = bar(x, y); // equivalent to p[x][y] = bar(x,y) in the array-of-arrays case
}
You can even avoid the multiplications as this is basically just a 1D iteration with additional generation of 2D indices
for(unsigned x = 0, idx = 0; x < N; ++x) for(unsigned y = 0; y < M; ++y, ++idx)
{
p[idx] = bar(x, y);
}