Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Copy std::map data to another map

I have a map that's defined like this

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

Then I have Amap1 and I want copy it to Amap2

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

Sometimes this work properly, sometimes this copies only the keys and the value 0. Where is my mistake here?

like image 201
herzl shemuelian Avatar asked Feb 24 '11 10:02

herzl shemuelian


People also ask

Does map insert copy?

Yes -- when you insert an item into an std::map, you pass it by value, so what it contains is a copy of what you passed.

Can C++ map have duplicate values?

C++ Software Engineering Multi-map in C++ is an associative container like map. It internally store elements in key value pair. But unlike map which store only unique keys, multimap can have duplicate keys.


Video Answer


2 Answers

Copying one map to another can be done with operator = or the copy constructor.

E.g

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)
like image 64
Armen Tsirunyan Avatar answered Oct 11 '22 07:10

Armen Tsirunyan


The code you've posted above will work correctly assuming that Amap2 is empty. If you try to insert a key/value pair into a map that already holds that key, then the old value will be kept and the new one will be discarded. For that reason, if you write

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

In some circumstances you might not copy everything over as intended, because duplicate keys won't copy.

To set Amap2 equal to Amap1, consider just using the assignment operator:

Amap2 = Amap1;

This will blindly discard the contents of Amap2, though, so be careful when doing this.

If what you want to do is add all the key/value pairs from Amap2 into Amap1 in a way that completely overrides the existing key/value pairs, you can do so using the following logic. The idea here is similar to the logic behind mergesort - we treat the maps as sequences of sorted values and then continuously blend the two together:

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

With this, you can write

MergeMaps(Amap1, Amap2);

To copy all the key/value pairs from Amap2 into Amap1.

Hope this helps!

like image 27
templatetypedef Avatar answered Oct 11 '22 07:10

templatetypedef