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

No comments:

Post a Comment