2011-10-05 6 views
10
map<T,Z> m= ...; 
vector<T> v; 
v.reserve(m.size); 
for(map<T,Z>::iterator it=m.begin();it!=m.end();++it) 
{ 
v.push_back(it->first); 
} 

¿Existe una versión de 1 línea más agradable el uso de alguna función (s) STL?Uso STL para poblar un vector <T> del mapa <T,Z> 's claves

editar: no usando C++ 11!

+2

Overkill? No está escribiendo demasiadas líneas de código para lograr esto de todos modos. –

+0

@Als: por esa lógica, gran parte del algoritmo std :: es igualmente inútil. –

+0

@Mahesh - Estaba pensando en alguna magia de inserción inversa, o algo –

Respuesta

8

portátil:

struct SelectKey { 
    template <typename F, typename S> 
    F operator()(const std::pair<const F, S> &x) const { return x.first; } 
}; 

std::transform(m.cbegin(), m.cend(), std::back_inserter(v), SelectKey()); 

creo que algunas implementaciones de STL tienen una extensión no estándar llamada select1st, que es el equivalente de SelectKey se muestra aquí. Como K-Ballo señaló en los comentarios, también hay una versión TR1. Me gusta la versión explícitamente nombrada, ya que es más fácil ver lo que está sucediendo.

Ya que no hay necesidad de estado, puede salirse con un poco menos repetitivo mediante el uso de una función real en lugar de un funtor:

template <typename F, typename S> 
F SelectKey()(const std::pair<const F, S> &x) { return x.first; } 

std::transform(m.cbegin(), m.cend(), std::back_inserter(v), SelectKey); 

Si usted podría utilizar C++ 11, se puede usar una lambda, que mantiene el código de selección de cerca de donde se utiliza:

std::transform(m.cbegin(), m.cend(), std::back_inserter(v), 
       [](const std::pair<const F, S> &x) { return x.first; }); 

o incluso de rango basada en bucle, que es probablemente el más elegante y legible:

for(const auto &x : m) { 
    v.push_back(x.first); 
} 
+1

¿Qué hay de lambda? será realmente un trazador de líneas entonces. – Dani

+2

Su 'operador()' debe ser 'const'. En TR1 esto podría lograrse con 'std :: bind (& map < T, Z > :: value_type :: first, _1)'. –

+3

No debe templatar la estructura, sino el 'operador()'. Y si realmente desea personalizar la estructura, debe proporcionar argumentos al crearla: 'SelectKey ()'. – Xeo

2

En C++ 11, puede utilizar las expresiones lambda:

typedef std::map< std::string, std::string > map_t; 
map_t map; 
std::vector<std::string> v; 

std::for_each(map.begin(), map.end(), [&v](map_t::value_type const& it) 
     { 
      v.push_back(it.first); 
     }); 
4

Pre C++ 11, que podría utilizar y transformar una función personalizada estructura:

template <class K, class V> 
struct key_selector : std::unary_function<const std::pair<K, V>&, const K&> 
{ 
    const K& operator()(const std::pair<K, V>& element) const 
    { 
     return element.first; 
    } 
}; 

transform(m.begin(), m.end(), back_inserter(v), key_selector<T,Z>()); 

Si tiene acceso para estimular o TR1, se puede reemplazar con key_selectormem_fn

transform(m.begin(), m.end(), back_inserter(v), mem_fn(&map<T,Z>::value_type::first)); 

Post-C++ 11, puede utilizar lambdas:

transform(m.begin(), m.end(), back_inserter(v), [](const map<T,Z>::value_type& x) {return x.first;}); 
+0

En pre C++ 11 no podías usar 'bind'. Si confía en extensiones no estándar o boost, dígalo. –

+0

@Christian: Cierto, con la advertencia de que antes de C++ 11 podrías usar 'std :: tr1 :: bind'. – ildjarn

+0

@ildjarn Sí, pero luego debería decirlo y no pretender que sea estándar. –

1

Usted puede hacer algo en la línea de:

std::transform(m.begin(), m.end(), std::back_inserter(v), FUNCTOR); 

Dónde Functor depende de la versión de la STL o bibliotecas y compiladores que tiene.

C++ 11 (lambda)

std::transform(m.begin(), m.end(), std::back_inserter(v), [](map<T,Z>::const_reference a) { return a.first; }); 

C++ 11 (std :: get)

std::transform(m.begin(), m.end(), std::back_inserter(v), &std::get<0>); 

C++ SGI STL tiene un llamado select1st funtor que puede ser utilizado

std::transform(m.begin(), m.end(), std::back_inserter(v), select1st); 

C++ 03 (No C++ 11) utilizando un objeto functor como otros han descrito.

Cuestiones relacionadas