102 votes

Copier les valeurs de la carte sur un vecteur en format STL

Travailler mon chemin à travers Effective STL pour le moment. L'élément 5 suggère qu'il est généralement préférable d'utiliser les fonctions de membre de la plage pour leurs équivalents élément unique. Je souhaite actuellement copier toutes les valeurs d'une carte (c'est-à-dire que je n'ai pas besoin des clés) sur un vecteur.

Quel est le moyen le plus propre de le faire?

73voto

Skurmedel Points 9227

Vous pourriez probablement utiliser std::transform à cette fin. Je préférerais peut-être la version Neils cependant, en fonction de ce qui est plus lisible.


Exemple avec xtofl (voir commentaires):

 #include <map>
#include <vector>
#include <algorithm>
#include <iostream>

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<int,bool> m;
    m[0]=true;
    m[1]=false;
    //...
    std::vector<bool> v;
    std::transform( m.begin(), m.end(), std::back_inserter( v ), second(m) );
    std::transform( m.begin(), m.end(), std::ostream_iterator<bool>( std::cout,     ";" ), second(m) );
}
 

Très générique, n'oubliez pas de lui donner du crédit si vous le trouvez utile.

24voto

OK. Points 755

Si vous utilisez les bibliothèques boost , vous pouvez utiliser boost :: bind pour accéder à la deuxième valeur de la paire comme suit:

 #include <string>
#include <map>
#include <vector>
#include <algorithm>
#include <boost/bind.hpp>

int main()
{
   typedef std::map<std::string, int> MapT;
   typedef std::vector<int> 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) );
}
 

Cette solution est basée sur un message de Michael Goldshteyn sur la liste de diffusion boost .

9voto

Loki Astari Points 116129

Voici ce que je ferais.
J'utiliserais également une fonction de modèle pour faciliter la construction de select2nd.

 #include <map>
#include <vector>
#include <algorithm>
#include <memory>
#include <string>

/*
 * A class to extract the second part of a pair
 */   
template<typename T>
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<typename T>
select2nd<typename T::value_type> make_select2nd(T const& m)
{
    return select2nd<typename T::value_type>();
}

int main()
{
    std::map<int,std::string>   m;
    std::vector<std::string>    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<std::map<int,std::string>::value_type>()
     */   
    std::transform(m.begin(),m.end(),
                   std::back_inserter(v),
                   make_select2nd(m)
                  );
}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X