Building a vector from components contained in another vector type

I have some code that looks something like this:

struct First { int f1; int f2; }; struct Second { First s1; int s2; }; std::vector < Second > secondVec; Second sec; sec.s1 = First(); secondVec.push_back(sec); secondVec.push_back(sec); std::vector < First > firstVec; firstVec.reserve(secondVec.size()); for (std::vector < Second >::iterator secIter = secondVec.begin(); secIter != = secondVec.end(); ++secIter) { firstVec.push_back(secIter->s1); } 

I would like to replace this ugly for loop with a simple stl function that could execute an equivalent process. I thought maybe std::transform might help me here, but I'm not sure how this could be written.

I would also be interested if boost has something to offer.

+4
source share
4 answers

If you have TR1 or Boost, you can try the following:

 std::transform(secondVec.begin(), secondVec.end(), std::back_inserter(firstVec), std::tr1::bind(&Second::s1, _1)); 
+7
source

Define a functor that converts Second to First:

 struct StoF { First operator()( const Second& s ) const { return s.s1; } }; 

Then use it as follows:

 transform( secondVec.begin(), secondVec.end(), back_inserter(firstVec), StoF() ); 

If your source vector contains many elements, you should consider resizing the destination vector so that it works faster, as in @Goz answer:

 firstVec.resize( secondVec.size() ); transform( secondVec.begin(), secondVec.end(), firstVec.begin(), StoF() ); 
+5
source

It is not particularly difficult ... I tried this and it did not work.

 struct First { int f1; int f2; }; struct Second { First s1; int s2; }; First Replace( Second& sec ) { return sec.s1; } 

and then the following code is used to copy it

 std::vector < Second > secondVec; Second sec; sec.s1.f1 = 0; sec.s1.f2 = 1; secondVec.push_back(sec); sec.s1.f1 = 2; sec.s1.f2 = 3; secondVec.push_back(sec); std::vector < First > firstVec; firstVec.resize( secondVec.size() ); std::transform( secondVec.begin(), secondVec.end(), firstVec.begin(), Replace ); 
+3
source

You were right with your intuition. Although, since you are using an empty vector, you should use the back inserter for your output iterator.

It should look something like:

 std::transform(secondVec.being(), secondVec.end(), back_inserter(firstVec), yourFunctor) 

And your Functioner looks like this:

 void youFunctor(First param) { return param.s1; } 

Edit: Boost can help you with the lambda function, so you don't need to create a separate functor for this task. It should also be noted that the function of the lambda function is part of TR1 and will be integrated into the standard C ++ library.

Edit: this is what Meredith said with mem_fun (or member-adapter).

  struct Second { First s1; int s2; First getS1() const {return s1;}; }; 

And then the conversion will look like this:

 std::transform(secondVec.being(), secondVec.end(), std::back_inserter(firstVec), std::mem_fun(&Second::getS1)) 
+2
source

All Articles