Blog coding and discussion of coding about JavaScript, PHP, CGI, general web building etc.

Wednesday, December 30, 2015

Copy map values to vector in STL

Copy map values to vector in STL


Working my way through Effective STL at the moment. Item 5 suggests that it's usually preferable to use range member functions to their single element counterparts. I currently wish to copy all the values in a map (i.e. - I don't need the keys) to a vector.

What is the cleanest way to do this?

Answer by anon for Copy map values to vector in STL


You can't easily use a range here becuase the iterator you get from a map refers to a std::pair, where the iterators you would use to insert into a vector refers to an object of the type stored in the vector, which is (if you are discarding the key) not a pair.

I really don't think it gets much cleaner than the obvious:

#include   #include   #include   using namespace std;    int main() {      typedef map  MapType;      MapType m;	      vector  v;        // populate map somehow        for( MapType::iterator it = m.begin(); it != m.end(); ++it ) {      	v.push_back( it->second );      }  }  

which I would probably re-write as a template function if I was going to use it more than once. Something like:

template    void MapToVec( const  M & m, V & v ) {      for( typename M::const_iterator it = m.begin(); it != m.end(); ++it ) {      	v.push_back( it->second );      }  }  

Answer by Skurmedel for Copy map values to vector in STL


You could probably use std::transform for that purpose. I would maybe prefer Neils version though, depending on what is more readable.


Example by xtofl (see comments):

#include   #include   #include   #include     template< typename tPair >  struct second_t {      typename tPair::second_type operator()( const tPair& p ) const { return     p.second; }  };    template< typename tMap >   second_t< typename tMap::value_type > second( const tMap& m ) { return second_t<     typename tMap::value_type >(); }      int main() {      std::map m;      m[0]=true;      m[1]=false;      //...      std::vector v;      std::transform( m.begin(), m.end(), std::back_inserter( v ), second(m) );      std::transform( m.begin(), m.end(), std::ostream_iterator( std::cout,     ";" ), second(m) );  }  

Very generic, remember to give him credit if you find it useful.

Answer by aJ. for Copy map values to vector in STL


One way is to use functor:

 template       class CopyMapToVec      {      public:           CopyMapToVec(std::vector& aVec): mVec(aVec){}            bool operator () (const std::pair& mapVal) const          {          	mVec.push_back(mapVal.second);          	return true;          }      private:          std::vector& mVec;      };      int main()  {      std::map myMap;      myMap["test1"] = 1;      myMap["test2"] = 2;        std::vector  myVector;        //reserve the memory for vector      myVector.reserve(myMap.size());      //create the functor      CopyMapToVec aConverter(myVector);        //call the functor      std::for_each(myMap.begin(), myMap.end(), aConverter);  }  

Answer by Loki Astari for Copy map values to vector in STL


Here is what I would do.
Also I would use a template function to make the construction of select2nd easier.

#include   #include   #include   #include   #include     /*   * A class to extract the second part of a pair   */     template  struct select2nd  {      typename T::second_type operator()(T const& value) const      {return value.second;}  };    /*   * A utility template function to make the use of select2nd easy.   * Pass a map and it automatically creates a select2nd that utilizes the   * value type. This works nicely as the template functions can deduce the   * template parameters based on the function parameters.    */  template  select2nd make_select2nd(T const& m)  {      return select2nd();  }    int main()  {      std::map   m;      std::vector    v;        /*       * Please note: You must use std::back_inserter()       *              As transform assumes the second range is as large as the first.       *              Alternatively you could pre-populate the vector.       *       * Use make_select2nd() to make the function look nice.       * Alternatively you could use:       *    select2nd::value_type>()       */         std::transform(m.begin(),m.end(),                     std::back_inserter(v),                     make_select2nd(m)                    );  }  

Answer by Matthieu N. for Copy map values to vector in STL


Using lambdas one can perform the following:

{     std::map m;     std::vector v;     v.reserve(m.size());     std::for_each(m.begin(),m.end(),                   [&v](const std::map::value_type& p)                    { v.push_back(p.second); });  }  

Answer by OK. for Copy map values to vector in STL


If you are using the boost libraries, you can use boost::bind to access the second value of the pair as follows:

#include   #include   #include   #include   #include     int main()  {     typedef std::map MapT;     typedef std::vector VecT;     MapT map;     VecT vec;       map["one"] = 1;     map["two"] = 2;     map["three"] = 3;     map["four"] = 4;     map["five"] = 5;       std::transform( map.begin(), map.end(),                     std::back_inserter(vec),                     boost::bind(&MapT::value_type::second,_1) );  }  

This solution is based on a post from Michael Goldshteyn on the boost mailing list.

Answer by OJMAN for Copy map values to vector in STL


I thought it should be

std::transform( map.begin(), map.end(), std::back_inserter(vec), boost::bind(&MapT::value_type::first,_1) );

Answer by skyhawk for Copy map values to vector in STL


Why not:

template  std::vector MapValuesAsVector(std::map map)  {     std::vector vec(map.size());     std::for_each(std::begin(map), std::end(map),          [&vec] (const std::map::value_type& entry)           {              vec.push_back(entry.second);          });      return vec;  }  

usage:

auto vec = MapValuesAsVector(anymap);

Answer by Seth for Copy map values to vector in STL


Old question, new answer. With C++11 we have the fancy new for loop:

for (const auto &s : schemas)     names.push_back(s.first);  

where schemas is a std::map and names is an std::vector.

This populates the array (names) with keys from the map (schemas); change s.first to s.second to get an array of values.


Fatal error: Call to a member function getElementsByTagName() on a non-object in D:\XAMPP INSTALLASTION\xampp\htdocs\endunpratama9i\www-stackoverflow-info-proses.php on line 72

0 comments:

Post a Comment

Popular Posts

Powered by Blogger.