Is there a way to slice the structure vector in c++? - c++

I have an data named faces which definition is like this:
struct ivec3 {
unsigned int v0;
unsigned int v1;
unsigned int v2;
};
std::vector<ivec3> faces;
I got the faces with 100 elements(faces.size()=100).
Now I want to get all v0 of faces. If I use the Python, I can do it like this
all_v0 = faces[:, 0]
So, how can I use the slicing operation in C++ like above code of Python?
Thanks very much!

You can do this with the help of std::transform:
std::vector<int> all_v0;
all_v0.reserve(faces.size());
std::transform(faces.begin(), faces.end(),
std::back_inserter(all_v0),
[] (const ivec3& i) { return i.v0; });

There is no "slicing operation" for vectors in C++.
But this can be done with a simple loop. Or, without writing the loop yourself by using a standard algorithm such as std::transform.
Consider whether you actually need a new container that has the "slices", or whether you would perhaps be content with having a range that can access those elements. This is analogous to using generator objects instead of creating the list in Python. Example:
auto get_v0 = [](const auto& v) -> auto {
return v.v0;
};
auto v0_range = std::ranges::transform_view(
faces,
get_v0
);
// access the objects:
for (auto v0 : v0_range) {
// use v0
}
// or if you do need a container:
std::vector v0s(begin(v0_range), end(v0_range));
Instead of the function, you can also use a member pointer as demonstrated in 康桓瑋's answer

You can pass in the corresponding member object pointer to C++20 views::transform to do this.
#include <ranges>
#include <vector>
struct ivec3 {
unsigned int v0;
unsigned int v1;
unsigned int v2;
};
int main() {
std::vector<ivec3> faces;
auto v0s = faces | std::views::transform(&ivec3::v0);
auto v1s = faces | std::views::transform(&ivec3::v1);
auto v2s = faces | std::views::transform(&ivec3::v2);
}

Related

Order a vector according to weights stored in another vector using STL algorithms

I have a vector containing instances of a class, let's say std::vector<A> a. I want to order this vector according to weights stored in a std::vector<float> weights, with weights[i] being the weight associated to a[i]; after sorting, a elements must be ordered by increasing weight.
I know how to do this explicitly, but I'd like to use C++14 STL algorithms in order to benefit from an eventual optimal implementation. Up to now, I haven't been able to figure how to use weights in a lambda comparison expression for std::sort, nor how to keep a and weights aligned every time two elements of a are swapped by std::sort, so I'm beginning to think that it might be not possible.
Thanks in advance for any help.
Sort an index vector, then rearrange according to the result:
void my_sort(std::vector<A>& a, std::vector<float>& weights)
{
std::vector<int> idx(a.size());
std::iota(idx.begin(), idx.end(), 0);
sort(idx.begin(), idx.end(),
[&](int a, int b) { return weights[a] < weights[b]; });
auto reorder = [&](const auto& o) {
decltype(o) n(o.size());
std::transform(idx.begin(), idx.end(), n.begin(),
[&](int i) { return o[i]; });
return n;
};
a = reorder(a);
weights = reorder(weights);
}
Transform the two vectors in a std::pair<A,float> vector and then sort based on the weight ( second member of the pair ) . Recreate the two vectors afterwards
Add a new member to the A class so that it contains the weight and sort based on that weight
make a custom comparison function based on a global array containing the weights like described here: std::sort and custom swap function
I would go for 3 as it is the most efficient. That is valid if you don't have multi-threading which would require some synchronization.
With my comment I was alluding exactly to what #AndreaRossini summarised with their comment. Something like this:
#include <boost/hana/functional/on.hpp>
#include <functional>
#include <iostream>
#include <range/v3/algorithm/sort.hpp>
#include <range/v3/view/transform.hpp>
#include <range/v3/view/zip.hpp>
#include <string>
#include <vector>
using boost::hana::on;
using namespace ranges;
using namespace ranges::views;
// helpers to get first and second of a pair
auto /*C++17->*/constexpr/*<-C++17*/ fst = [](auto const& p){ return p.first; };
auto /*C++17->*/constexpr/*<-C++17*/ snd = [](auto const& p){ return p.second; };
int main(){
std::vector<std::string> v{"one", "two", "three"}; // values
std::vector<float> w{3,1,2}; // weights
// zipping the two sequences; each element of vw is a pair
auto vw = zip(v, w);
// sorting: using `std::less` on the `snd` element of the pairs
sort(vw, std::less<>{} ^on^ snd);
// extracting only the `fst` of each pair
auto res = vw | transform(fst);
// show result
for (auto i : res) { std::cout << i << std::endl; }
}
A few things about the libraries that I've used:
res is not a std::vector but just a view; if you want a vector, you can do
#include <range/v3/range/conversion.hpp>
auto res = vw | transform(fst) | to_vector;
std::less<>{} ^on^ snd is equivalent to the following f
auto f = [](auto const& x, auto const& y){
return std::less<>{}(snd(x), snd(y));
};
so you can think of it as a function that takes x and y and gives back snd(x) < snd(y).

assign values to member of a struct with a for loop

I have a struct of the form
struct Thing {
std::vector<bool> A;
std::vector<int> B;
};
in the main the struct is created inside a for loop and used as the input to a function
for(int i=0;i<50;i++) {
Thing temporalthing;
temporalthing.A=A;
temporalthing.B=B;
temporalresult=fun1(temporalthing,data)
}
A and B are hardcoded into a series of vectors stored like this
std::vector<bool> A1{ 1,0,1};
std::vector<int> B1{ 2,1,3};
std::vector<bool> A2{ 0,1,1};
std::vector<int> B2{ 4,2,3}; ....
I want for each iteration of the for loop to take the corresponding value of A and B (loop 1 take A1 and B1, loop 2 take A2 and B2, ETC), if this were MATLAB this would be easy using reflection but I understand C++ does not have reflection, my other option would be to use a Switch Case structure of 50 different values that surely would work but I am not sure if this is the most optimal way to do it. Is there a better way?
I am new to C++ having a lot more experience with MATLAB but trying to learn... any help is very appreciated
My suggestion:
Change
temporalthing.A=A;
temporalthing.B=B;
to
temporalthing.A = getA(i);
temporalthing.B = getB(i);
The functions getA() and getB() can use whatever logic to return you an A and a B for the given i.
A simple implementation for getA() would be to store the various As in a vector.
std::vector<int>& getA(size_t i)
{
static std::vector<std::vector<int>> aList;
if ( aList.empty() )
{
// Fill up the list
aList[0] = {1, 0, 1};
aList[1] = {0, 1, 1};
// etc.
}
return aList[i];
}
Do the same thing for getB().
If getA() can use i to compute the return value, then, it does not have to store the As.
std::vector<int> getA(size_t i)
{
int v1 = func1(i);
int v2 = func2(i);
int v3 = func3(i);
return {v1, v2, v3};
}

How do I pass an Eigen matrix row reference, to be treated as a vector?

I have a function that operates on a Vector reference, e.g.
void auto_bias(const Eigen::VectorXf& v, Eigen:Ref<Eigen::VectorXf>> out)
{
out = ...
}
and at some point I need to have this function operate on a Matrix row. Now, because the default memory layout is column-major, I can't just Map<> the data the row points to into a vector. So, how do I go about passing the row into the above function so that I can operate on it?
The not-so-pretty solution is to have a temp vector, e.g.
VectorXf tmpVec = matrix.row(5);
auto_bias(otherVector, tmpVec);
matrix.row(5) = tmpVec;
but is there a way of doing it directly?
You can modify your function to take a reference to the row type (which is a vector expression) instead of a vector. This is really only manageable with a template to infer that type for you:
#include <iostream>
#include <Eigen/Core>
template<typename V>
void set_row(V&& v) {
v = Eigen::Vector3f(4.0f, 5.0f, 6.0f);
}
int main() {
Eigen::Matrix3f m = Eigen::Matrix3f::Identity();
set_row(m.row(1));
std::cout << m;
return 0;
}
You can allow Ref<> to have a non default inner-stride (also called increment), as follows:
Ref<VectorXf, 0, InnerStride<>>
See the example function foo3 of the Ref's documentation.
The downside is a possible loss of performance even when you are passing a true VectorXf.

How To Use Vector Points in C++ OpenCv?

Could you guys Please help me in providing good notes or links ?
For Ex : I need to create a vector and dump these x,y values in Vector ..
Data { X , Y } = {1,1} , {1,2} , {1,3}, {2,1},{2,2},{2,3},{3,1},{3,2},{3,3}
A vector of point in OpenCV is just a standard C++ STL vector containing OpenCV Point objects :
std::vector<Point> data;
data.push_back(Point(1,1));
data.push_back(Point(1,2));
data.push_back(Point(1,3));
data.push_back(Point(2,1));
...
Alternatively, if you're using C++11 or later you can use a list initialization:
std::vector<Point> data = {Point(1,1), Point(1,2), Point(1,3), Point(2,1)};
Take a look at the C++ reference for STL Vector
So... you want to use a vector to store data... wherein each element is a pair of ints? Well, if you don't want to create your own type, use a tuple or pair:
#include <vector>
#include <utility>
// ...
std::vector<std::pair<int, int> v;
// ...
v.push_back(std::make_pair(1, 1));
// ...
auto p = c[offset];
int x = p.first;
int y = p.second;

sum of square of each elements in the vector using for_each

As the function accepted by for_each take only one parameter (the element of the vector), I have to define a static int sum = 0 somewhere so that It can be accessed
after calling the for_each . I think this is awkward. Any better way to do this (still use for_each) ?
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
static int sum = 0;
void add_f(int i )
{
sum += i * i;
}
void test_using_for_each()
{
int arr[] = {1,2,3,4};
vector<int> a (arr ,arr + sizeof(arr)/sizeof(arr[0]));
for_each( a.begin(),a.end(), add_f);
cout << "sum of the square of the element is " << sum << endl;
}
In Ruby, We can do it this way:
sum = 0
[1,2,3,4].each { |i| sum += i*i} #local variable can be used in the callback function
puts sum #=> 30
Would you please show more examples how for_each is typically used in practical programming (not just print out each element)? Is it possible use for_each simulate 'programming pattern' like map and inject in Ruby (or map /fold in Haskell).
#map in ruby
>> [1,2,3,4].map {|i| i*i}
=> [1, 4, 9, 16]
#inject in ruby
[1, 4, 9, 16].inject(0) {|aac ,i| aac +=i} #=> 30
EDIT: Thank you all. I have learned so much from your replies. We have so many ways to do the same single thing in C++ , which makes it a little bit difficult to learn. But it's interesting :)
No, don't use std::accumulate() use std::inner_product(). No functor required.
#include <vector>
#include <numeric>
void main()
{
std::vector <int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
int x = std::inner_product( v1.begin(), v1.end(), v1.begin(), 0 );
}
Use std::accumulate
#include <vector>
#include <numeric>
// functor for getting sum of previous result and square of current element
template<typename T>
struct square
{
T operator()(const T& Left, const T& Right) const
{
return (Left + Right*Right);
}
};
void main()
{
std::vector <int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
int x = std::accumulate( v1.begin(), v1.end(), 0, square<int>() );
// 0 stands here for initial value to which each element is in turn combined with
// for our case must be 0.
}
You could emulate std::accumulate as in nice GMan's answer, but I believe that using std::accumulate will make your code more readable, because it was designed for such purposes. You could find more standard algorithms here.
for_each returns (a copy of) the functor that it was using. So, something like this:
#include <algorithm>
#include <vector>
#include <iostream>
template <typename T>
class square_accumulate
{
public:
square_accumulate(void) :
_sum(0)
{
}
const T& result(void) const
{
return _sum;
}
void operator()(const T& val)
{
_sum += val * val;
}
private:
T _sum;
};
int main(void)
{
int arr[] = {1,2,3,4};
std::vector<int> a (arr ,arr + sizeof(arr)/sizeof(arr[0]));
int sum = std::for_each(a.begin(), a.end(), square_accumulate<int>()).result();
std::cout << "sum of the square of the element is " << sum << std::endl;
}
As demonstrated by other answers, though, std::accumulate is the best way to go.
Don't use for_each() for this, use accumulate() from the <numeric> header:
#include <numeric>
#include <iostream>
using namespace std;
struct accum_sum_of_squares {
// x contains the sum-of-squares so far, y is the next value.
int operator()(int x, int y) const {
return x + y * y;
}
};
int main(int argc, char **argv) {
int a[] = { 4, 5, 6, 7 };
int ssq = accumulate(a, a + sizeof a / sizeof a[0], 0, accum_sum_of_squares());
cout << ssq << endl;
return 0;
}
The default behaviour of accumulate() is to sum elements, but you can provide your own function or functor as we do here, and the operation it performs need not be associative -- the 2nd argument is always the next element to be operated on. This operation is sometimes called reduce in other languages.
You could use a plain function instead of the accum_sum_of_squares functor, or for even more genericity, you could make accum_sum_of_squares a class template that accepts any numeric type.
As a general solution to such issue with STL: instead of passing a function, you can pass a functor -- for example, an instance of any class implementing operator(). This is much better than relying on global variables, since said instance can keep and update its own state! You could think of it as a kind of "compile time duck typing": generic programming does not constrain you to pass a "function" in that place, anything that "behaves like a function" (i.e., has a proper operator()) will do as well!-)
std::for_each is for doing something with each element. If you want get a result from a calculation on all the elements, there's std::accumulate. If you are wanting Haskell's map behaviour, use std::transform.
You can abuse either of these three to do the same thing as any of the others, since ultimately they are just iterating over an iterator (except for transform's form that takes two iterators as input.) The point is that for_each is not a replacement for map/fold - that should be done by transform/accumulate - although C++ doesn't natively have something that expresses the map/fold concept as well as Haskell does - but both gcc and VC++ support OpenMP which has a much better analogue in #pragma omp parallel for.
Inject in Ruby is a much closer match to calling for_each with a full-fledged functor, like GMan explained above. Lambda functions with variable capture in C++0X will make the behaviour between the two languages even more similar:
int main(void)
{
int arr[] = {1,2,3,4};
std::vector<int> a (arr ,arr + sizeof(arr)/sizeof(arr[0]));
int sum = 0;
std::for_each(a.begin(), a.end(), [&](int i) { sum += i*i;} );
std::cout << "sum of the square of the element is " << sum << std::endl;
}