2009-03-26 18 views
17

¿Cuál es la mejor manera en C++ para copiar un par de un mapa a vector? Estoy haciendo esto para luego poder ordenar el vector.C++ cómo copiar un mapa en un vector

+2

Pregunta muy vaga – camh

+1

Los mapas están ordenados. Debe especificar si desea ordenar otro parámetro o con una clave diferente. De lo contrario, la pregunta es auto-respondida: no. –

Respuesta

19

Esto debería hacer lo que quiera:

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

using namespace std; 

bool cmp(const pair<int, int> &p1, const pair<int, int> &p2) 
{ 
    return p1.second < p2.second; 
} 

int main() 
{ 
    map<int, int> m; 
    for(int i = 0; i < 10; ++i) 
     m[i] = i * -i; 

    vector<pair<int, int> > v; 
    copy(m.begin(), m.end(), back_inserter(v)); 

    sort(v.begin(), v.end(), cmp); 

    for(int i = 0; i < v.size(); ++i) 
     cout << v[i].first << " : " << v[i].second << endl; 
    return 0; 
} 
2

A map almacena un par: una clave y un valor. ¿Qué parte quieres copiar? O bien, ¿desea copiar ambos en dos vector s distintos?

Quiero copiar ambos. Una vez hecho esto, tengo que averiguar cómo ordenar el vector por el segundo valor en el par.

template <class V> 
struct sort_by_val { 
    bool operator()(V const& l, V const& r) { 
     return // ... 
    } 
}; 

vector<pair<K, V> > outv(map.begin(), map.end()); 

sort(outv.begin(), outv.end(), sort_by_val()); 
+0

Quiero copiar ambos. Una vez hecho esto, necesito descubrir cómo ordenar el vector por el * segundo * valor en el par. –

+0

+1, solución clara y simple. @Jack: realmente debes incluir la información en tu comentario en la pregunta principal, ya que es muy relevante, por ej. hubiera impedido que todos mencionaran que los mapas ya están ordenados por sus primeros elementos. –

6

Si está utilizando un std :: mapa, que ya está ordenado por la clave. Simplemente crea un iterador e itera sobre el mapa desde begin() hasta end() y listo.

Si desea ordenar por otra cosa que no sea la tecla de mapa, puede usar el mismo iterador e insertar una copia de cada elemento en su vector mientras itera sobre el mapa.

+0

Puede ser incluso más simple: puede especificar un comparador en el mapa CTor. – foraidt

25
vector<pair<K,V> > v(m.begin(), m.end()); 

o

vector<pair<K,V> > v(m.size()); 
copy(m.begin(), m.end(), v.begin()); 

copy() es en <algorithm>.

+2

Este parece ser más elegante y simple – Ram

+1

Sí, este es el mejor, especialmente el primero. Solo unos pocos comentarios explicativos: si tiene 'typedef std :: map MapType' no puede declarar el vector' vector 'como value_type es' pair 'que no tiene operador = y no puede ser copiado en el vector.Además, en el segundo ejemplo, es realmente importante pasar el tamaño del vector primero (ya sea a través del constructor o de la reserva) porque la copia no asignará espacio en el vector a medida que se agreguen los elementos y existe una gran posibilidad de que se ejecute sobre el fin de la asignación inicial del vector. –

+1

'copy (m.begin(), m.end(), v.begin());' me dio una falla de segmentación. Solo digo. – yasith

2

Suponiendo que desea copiar la clave y el valor:

std::map<Foo, Bar> m; 


// Map gets populated 
// (...) 


// Copying it to a new vector via the constructor 
std::vector<std::pair<Foo, Bar>> v(m.begin(), m.end()); 


// Copying it to an existing vector, erasing the contents 
v.assign(m.begin(), m.end()); 

// Copying it to the back of an existing vector 
v.insert(v.end(), m.begin(), m.end()); 
+0

Ese último es incorrecto. Tal vez te refieres a v.insert (v.rbegin(). Base(), m.begin(), m.end()); ? – wilhelmtell

+0

whihelmtell - ¿Por qué crees que es incorrecto? Lo probé, funciona bien. –

+0

Ahora que lo pienso: v.rebegin(). Base() devuelve el mismo iterador que v.end() –

2

Si su propósito es sólo para ordenar por el tipo de lugar de la tecla , es posible que desee mirar Boost::Bimap. Le permite acceder a ambas partes del par de mapas como claves. Presumiblemente, podría iterar sobre él en orden de la segunda clave tan fácilmente como la primera.

0

Puede utilizar un mapa diferente (o conjunto) y el uso de transformación para realizar la ordenación al insertar:

#include <map> 
#include <algorithm> 

typedef std::map<unsigned int, signed char> MapType1; 
typedef std::map<MapType1::mapped_type, MapType1::key_type> MapType2; 

struct SwapPair 
{ 
    MapType2::value_type operator()(MapType1::value_type const & v) 
    { 
    return std::make_pair (v.second, v.first); 
    } 
}; 

int main() 
{ 
    MapType1 m1; 
    for(int i = 0; i < 10; ++i) 
    m1[i] = i * -i; 

    MapType2 m2; 
    std::transform (m1.begin() 
     , m1.end() 
     , std::inserter (m2, m2.end()) 
     , SwapPair()); 
} 

me olvidó añadir que si se tiene que hacer esto mucho, entonces puede ser mejor solo para usar un contenedor multi-index boost.

Cuestiones relacionadas