Pregunta

Esta es una de las posibles maneras en que me salen:

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 por definir otro functor RetrieveValues.

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

¿Fue útil?

Solución

Mientras que la solución debe trabajar, puede ser difícil de leer, dependiendo del nivel de habilidad de sus compañeros programadores.Además, se mueve la funcionalidad de distancia desde el sitio de llamada.Que puede hacer el mantenimiento es un poco más difícil.

No estoy seguro de si su objetivo es conseguir las llaves en un vector o de impresión a cout así que estoy haciendo.Usted 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 más simple aún, si usted está utilizando 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 el BOOST_FOREACH versión porque no es escribir menos y es muy explícito acerca de lo que está haciendo.

Otros consejos

//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);

Hay un impulsar la gama adaptador para este propósito:

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

Hay una similar map_values gama adaptador para la extracción de los valores.

C++0x nos ha dado una más, una solución 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;});

@DanDan la respuesta, el uso de 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 el uso de C++14 (como se nota por @ivan.ukr) se puede sustituir decltype(map_in)::value_type con auto.

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

Creo que el BOOST_FOREACH presentada es agradable y limpio, sin embargo, hay otra opción de usar BOOST así.

#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 es tan limpio como el BOOST_FOREACH enfoque en este caso, pero boost::lambda puede ser realmente limpio en otros casos.

La solución está bien, pero puedes 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
}

También, si usted tiene Boost, uso transform_iterator para evitar la realización de copia temporal de las teclas.

Usted puede utilizar el versátil boost::transform_iterator.El transform_iterator permite transformar la iteración de valores, por ejemplo en nuestro caso cuando se desea tratar sólo con las llaves, no en los valores.Ver http://www.boost.org/doc/libs/1_36_0/libs/iterator/doc/transform_iterator.html#example

Poco de c++11:

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;
}

El mejor no-sgi, no aumentar STL solución es ampliar el mapa::iterator así:

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 usarlos como:

        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];

Aquí tienes una buena plantilla de función con C++11 de magia, trabajando tanto 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;
}

Échale un vistazo aquí: http://ideone.com/lYBzpL

Ligeramente similar a uno de los ejemplos aquí, la simplificación de std::map el uso de la perspectiva.

template<class KEY, class VALUE>
std::vector<KEY> getKeys(const std::map<KEY, VALUE>& map)
{
    std::vector<KEY> keys(map.size());
    for (const auto& it : map)
        keys.push_back(it.first);
    return keys;
}

Uso como esta:

auto keys = getKeys(yourMap);

Basado en @rusty-parques solución, pero en c++17:

std::map<uint32_t, uint32_t> items;
std::vector<uint32_t> itemKeys;
for (auto const& [key, std:ignore] : items) {
  itemKeys.emplace_back(key);
}

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

Porque no puede hacerlo mejor que usted puede hacer.Si una implementación del método no será superior a un libre en función de la aplicación, a continuación, en general no se debe escribir un método;usted debe escribir una función libre.

Además no es inmediatamente claro por qué es útil de todos modos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top