2011-02-24 24 views
15

tengo un mapa que está definido como estoCopiar std :: mapa de datos a otro mapa

struct A 
{ 
    int A; 
    int B; 
}; 
typedef map<int,A> Amap; 

Entonces tengo Amap1 y quiero copiarlo en Amap2

A a....; 
Amap Amap1,Amap2; 
Amap1[1]=a1; 
Amap1[2]=a2; 
Amap1[3]=a3; 
Amap2.insert(Amap1.begin(), Amap1.end()); 

A veces este trabajo correctamente, a veces esto copia solo las teclas y el valor 0. ¿Dónde está mi error aquí?

Respuesta

34

En primer lugar, es std::map, no stl::map :)

Y en segundo lugar copiado un mapa a otro se puede hacer con el operador = o el constructor de copia.

por ejemplo

map<X, Y> mp1; 
//fill mp1 with data 
map<X, Y> mp2(mp1); //mp2 is a copy of mp1 (via copy-construction) 
map<X, Y> mp3; 
mp3 = mp2; // mp3 is also a copy of mp2 (via copy-assignment) 
+0

@ Wolf: Ambos métodos se presentan en la respuesta. Esta es una comunidad editada colaborativamente, si desea agregar algo a la respuesta, siéntase libre de editarla. –

+0

@ Wolf: no modifique sustancialmente las respuestas de otras personas, especialmente las que se escribieron CINCO años atrás, que ya han sido votadas por personas y aceptadas por el OP. Siéntase libre de escribir su propia respuesta competitiva. –

+0

@LightnessRacesinOrbit Lo pedí y el OP me lo concedió explícitamente: * 'siéntase libre de editarlo' * – Wolf

13

El código que has enviado anterior funcionará correctamente suponiendo que Amap2 está vacía. Si intentas insert un par clave/valor en un map que ya tiene esa clave, se mantendrá el valor anterior y se descartará el nuevo. Por esa razón, si se escribe

Amap2.insert(Amap1.begin(), Amap1.end()); 

En algunas circunstancias, es posible que no copiar todos los objetos según lo previsto, porque las claves duplicadas no copiarán.

Para establecer Amap2 igual a Amap1, consideran simplemente usando el operador de asignación:

Amap2 = Amap1; 

Esto descartará ciegamente el contenido de Amap2, sin embargo, así que tenga cuidado al hacer esto.

Si lo que quiere hacer es agregar todos los pares de clave/valor de Amap2 en Amap1 de manera que anule completamente los pares clave/valor existentes, puede hacerlo usando la siguiente lógica. La idea aquí es similar a la lógica detrás de mergesort - tratamos a los mapas como secuencias de valores ordenados y luego se mezcla de forma continua a los dos juntos:

void MergeMaps(map<int, A>& lhs, const map<int, A>& rhs) { 
    map<int, A>::iterator lhsItr = lhs.begin(); 
    map<int, A>::const_iterator rhsItr = rhs.begin(); 

    while (lhsItr != lhs.end() && rhsItr != rhs.end()) { 
     /* If the rhs value is less than the lhs value, then insert it into the 
      lhs map and skip past it. */ 
     if (rhsItr->first < lhsItr->first) { 
      lhs.insert(lhsItr, *rhsItr); // Use lhsItr as a hint. 
      ++rhsItr; 
     } 
     /* Otherwise, if the values are equal, overwrite the lhs value and move both 
      iterators forward. */ 
     else if (rhsItr->first == lhsItr->first) { 
      lhsItr->second = rhsItr->second; 
      ++lhsItr; ++rhsItr; 
     } 
     /* Otherwise the rhs value is bigger, so skip past the lhs value. */ 
     else 
      ++lhsItr; 

    } 

    /* At this point we've exhausted one of the two ranges. Add what's left of the 
     rhs values to the lhs map, since we know there are no duplicates there. */ 
    lhs.insert(rhsItr, rhs.end()); 
} 

Con esto, se puede escribir

MergeMaps(Amap1, Amap2); 

Para copiar todos los pares clave/valor de Amap2 en Amap1.

Espero que esto ayude!

+2

Si quería asegurar que las claves existentes se sobrescribieran, hay dos opciones que podría elegir: Yo usaría std :: copy pero en vez de 'std :: inserter 'Escribiría uno personalizado que usara' operator [] '. La alternativa de 2 líneas, aunque posiblemente no tan eficiente, es copiar rhsItr luego regular-insertar lhsItr en la copia y luego intercambiar. – CashCow

+1

@CashCow: La principal ventaja de mi enfoque en comparación con el insertado personalizado es que los corchetes se ejecutan en el caso promedio O (lg n) mientras que el código que publiqué debe ejecutarse en tiempo lineal, suponiendo una buena implementación de inserción, debido a la insinuando tener el iterador cercano. – templatetypedef

Cuestiones relacionadas