Como recuperar todas as chaves (ou valores) de um std :: map e colocá-los em um vetor?

Esta é uma das maneiras possíveis de sair:

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

É claro que também podemos recuperar todos os valores do mapa definindo outro functor RetrieveValues .

Existe alguma outra maneira de conseguir isso facilmente? (Eu sempre estou me perguntando por que o std :: map não inclui uma function de membro para fazer isso.)

Enquanto sua solução deve funcionar, pode ser difícil de ler, dependendo do nível de habilidade de seus colegas programadores. Além disso, ele move a funcionalidade para longe do site de chamada. O que pode tornar a manutenção um pouco mais difícil.

Não tenho certeza se seu objective é colocar as chaves em um vetor ou imprimi-las para que eu faça as duas coisas. Você pode tentar algo assim:

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

Ou ainda mais simples, se você estiver usando o Boost:

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

Pessoalmente, eu gosto da versão BOOST_FOREACH porque há menos digitação e é muito explícito sobre o que está fazendo.

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

Existe um adaptador de faixa de impulso para este propósito:

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

Há um adaptador de intervalo map_values ​​semelhante para extrair os valores.

C ++ 0x nos deu mais uma excelente solução:

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

O SGI STL tem uma extensão chamada select1st . Pena que não está no STL padrão!

Eu acho que o BOOST_FOREACH apresentado acima é bom e limpo, no entanto, há outra opção usando o BOOST também.

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

Pessoalmente, eu não acho que esta abordagem é tão limpa quanto a abordagem BOOST_FOREACH neste caso, mas boost :: lambda pode ser realmente limpa em outros casos.

@ Resposta do DanDan, usando C + + 11 é:

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

e usando C ++ 14 (como observado por @ ivan.ukr) podemos replace decltype(map_in)::value_type por auto .

Sua solução está bem, mas você pode usar um iterador para fazer isso:

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

Além disso, se você tiver Boost, use transform_iterator para evitar fazer uma cópia temporária das chaves.

Você pode usar o versátil boost :: transform_iterator. O transform_iterator permite transformar os valores iterados, por exemplo, no nosso caso, quando você deseja lidar apenas com as chaves, não com os valores. Veja http://www.boost.org/doc/libs/1_36_0/libs/iterator/doc/transform_iterator.html#example

A melhor solução STL não-sgi, sem reforço, é estender o map :: iterator da seguinte forma:

 template 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 key_iterator key_begin(map_type& m) { return key_iterator(m.begin()); } template key_iterator key_end(map_type& m) { return key_iterator(m.end()); } 

e depois usá-los assim:

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

Um pouco de um c ++ 11 take:

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

Aqui está um bom modelo de function usando a mágica do C ++ 11, trabalhando para ambos std :: map, std :: unordered_map:

 template 

Confira aqui: http://ideone.com/lYBzpL

(Eu sempre estou me perguntando por que o std :: map não inclui uma function de membro para fazer isso.)

Porque não pode fazer nada melhor do que você pode fazer. Se a implementação de um método não for superior à implementação de uma function livre, então, em geral, você não deve escrever um método; você deveria escrever uma function grátis.

Também não está imediatamente claro por que é útil de qualquer maneira.