que programacion libreria funciona ejemplo diccionarios como c++ dictionary stl stdmap

c++ - programacion - ¿Cómo recuperar todas las claves(o valores) de un std:: map y ponerlas en un vector?



que es un map en c++ (14)

(Siempre me pregunto por qué std :: map no incluye una función de miembro para que lo hagamos).

Porque no puede hacerlo mejor de lo que puedes hacerlo. Si la implementación de un método no será superior a la implementación de una función gratuita, entonces, en general, no debe escribir un método; deberías escribir una función gratuita.

Tampoco está claro de inmediato por qué es útil de todos modos.

Esta es una de las posibles formas en que salgo:

struct RetrieveKey { template <typename T> typename T::first_type operator()(T keyValuePair) const { return keyValuePair.first; } }; map<int, int> m; vector<int> keys; // Retrieve all keys transform(m.begin(), m.end(), back_inserter(keys), RetrieveKey()); // Dump all keys copy(keys.begin(), keys.end(), ostream_iterator<int>(cout, "/n"));

Por supuesto, también podemos recuperar todos los valores del mapa definiendo otro functor RetrieveValues .

¿Hay alguna otra forma de lograr esto fácilmente? (Siempre me pregunto por qué std :: map no incluye una función de miembro para que lo hagamos).


Además, si tiene Boost, use transform_iterator para evitar hacer una copia temporal de las claves.


Aquí hay una plantilla de función agradable que utiliza magia C ++ 11, que funciona tanto para std :: map, std :: unordered_map:

template<template <typename...> class MAP, class KEY, class VALUE> std::vector<KEY> keys(const MAP<KEY, VALUE>& map) { std::vector<KEY> result; result.reserve(map.size()); for(const auto& it : map){ result.emplace_back(it.first); } return result; }

Compruébelo aquí: http://ideone.com/lYBzpL


C ++ 0x nos ha dado una solución adicional excelente:

std::vector<int> keys; std::transform( m_Inputs.begin(), m_Inputs.end(), std::back_inserter(keys), [](const std::map<int,int>::value_type &pair){return pair.first;});


Creo que el BOOST_FOREACH presentado anteriormente es bueno y limpio, sin embargo, hay otra opción que también usa BOOST.

#include <boost/lambda/lambda.hpp> #include <boost/lambda/bind.hpp> std::map<int, int> m; std::vector<int> keys; using namespace boost::lambda; transform( m.begin(), m.end(), back_inserter(keys), bind( &std::map<int,int>::value_type::first, _1 ) ); copy( keys.begin(), keys.end(), std::ostream_iterator<int>(std::cout, "/n") );

Personalmente, no creo que este enfoque sea tan limpio como el enfoque BOOST_FOREACH en este caso, pero boost :: lambda puede ser realmente limpio en otros casos.


El SGI STL tiene una extensión llamada select1st . Lástima que no está en STL estándar.


Hay un adaptador de rango de impulso para este propósito:

vector<int> keys; // Retrieve all keys boost::copy(m | boost::adaptors::map_keys, std::back_inserter(keys));

Hay un adaptador de rango map_values ​​similar para extraer los valores.


La mejor solución STL que no es sgi ni boost es extender map :: iterator de la siguiente manera:

template<class map_type> class key_iterator : public map_type::iterator { public: typedef typename map_type::iterator map_iterator; typedef typename map_iterator::value_type::first_type key_type; key_iterator(const map_iterator& other) : map_type::iterator(other) {} ; key_type& operator *() { return map_type::iterator::operator*().first; } }; // helpers to create iterators easier: template<class map_type> key_iterator<map_type> key_begin(map_type& m) { return key_iterator<map_type>(m.begin()); } template<class map_type> key_iterator<map_type> key_end(map_type& m) { return key_iterator<map_type>(m.end()); }

y luego utilícelos así:

map<string,int> test; test["one"] = 1; test["two"] = 2; vector<string> keys; // // method one // key_iterator<map<string,int> > kb(test.begin()); // key_iterator<map<string,int> > ke(test.end()); // keys.insert(keys.begin(), kb, ke); // // method two // keys.insert(keys.begin(), // key_iterator<map<string,int> >(test.begin()), // key_iterator<map<string,int> >(test.end())); // method three (with helpers) keys.insert(keys.begin(), key_begin(test), key_end(test)); string one = keys[0];


La respuesta de @ DanDan, usando C ++ 11 es:

using namespace std; vector<int> keys; transform(begin(map_in), end(map_in), back_inserter(keys), [](decltype(map_in)::value_type const& pair) { return pair.first; });

y usando C ++ 14 (como lo señala @ ivan.ukr) podemos reemplazar decltype(map_in)::value_type con auto .



Si bien su solución debería funcionar, puede ser difícil de leer dependiendo del nivel de habilidad de sus compañeros programadores. Además, aleja la funcionalidad del sitio de llamadas. Lo cual puede hacer que el mantenimiento sea un poco más difícil.

No estoy seguro de si tu objetivo es poner las llaves en un vector o imprimirlas para que las use, así que estoy haciendo las dos cosas. Puede intentar algo como esto:

map<int, int> m; vector<int> v; for(map<int,int>::iterator it = m.begin(); it != m.end(); ++it) { v.push_back(it->first); cout << it->first << "/n"; }

O incluso más simple, si estás usando Boost:

map<int,int> m; pair<int,int> me; // what a map<int, int> is made of vector<int> v; BOOST_FOREACH(me, m) { v.push_back(me.first); cout << me.first << "/n"; }

Personalmente, me gusta la versión BOOST_FOREACH porque hay menos tipeo y es muy explícito sobre lo que está haciendo.


Su solución está bien pero puede usar un iterador para hacerlo:

std::map<int, int> m; m.insert(std::pair<int, int>(3, 4)); m.insert(std::pair<int, int>(5, 6)); for(std::map<int, int>::const_iterator it = m.begin(); it != m.end(); it++) { int key = it->first; int value = it->second; //Do something }


Un poco de c ++ 11 tomar:

std::map<uint32_t, uint32_t> items; std::vector<uint32_t> itemKeys; for (auto & kvp : items) { itemKeys.emplace_back(kvp.first); std::cout << kvp.first << std::endl; }


//c++0x too std::map<int,int> mapints; std::vector<int> vints; vints.reserve(mapints.size()); for(auto const& imap: mapints) vints.push_back(imap.first);