2011-02-24 110 views
15

我有一個已定義這樣複製的std ::地圖數據到另一個地圖

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

然後,我有Amap1,我想有時候,這正常工作將其複製到Amap2

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

地圖,有時候這隻會複製鍵和值0.我的錯誤在哪裏?

回答

34

首先,它是std::map,不stl::map :)

而第二複製一個映射到另一個可與運營商=或拷貝構造函數來完成。

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) 
+0

@Wolf:這兩種方法都在答案中給出。這是一個協作編輯的社區,如果您想添加答案,請隨時編輯它。 – 2016-05-11 13:13:55

+0

@Wolf:請不要大幅修改其他人的答案,尤其是那些在5年前寫過的,已經被人們上傳並被OP接受的答案。隨意編寫自己的,相互競爭的答案。 – 2016-05-11 13:29:39

+0

@LightnessRacesinOrbit我問過它,OP明確授予給我:*'隨意編輯它* – Wolf 2016-05-11 13:31:40

13

你上面貼的代碼將正常工作假設Amap2是空的。如果您嘗試將insert鍵/值對存儲到已保存該鍵的map中,則舊值將被保留,並且新值將被丟棄。因爲這個原因,如果你寫

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

在某些情況下,你可能不會按照預期複製一切,因爲重複鍵不會複製。

要設置Amap2等於Amap1,考慮只使用賦值運算符:

Amap2 = Amap1; 

這會盲目地丟棄的Amap2的內容,但是,這樣做時要小心。

如果你想要做的是增加從Amap2所有的鍵/值對到Amap1在完全覆蓋現有的鍵/值對的方式,你可以這樣做使用下面的邏輯。這裏的想法是相似的背後歸併邏輯 - 我們把地圖作爲排序的值序列,然後不斷融合兩者結合起來:

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

有了這個,你可以寫

MergeMaps(Amap1, Amap2); 

複製從Amap2Amap1的所有鍵/值對。

希望這會有所幫助!

+2

如果我想確保現有的密鑰被覆蓋有2個選項,我可以選擇:我會或者使用std :: copy,而不是'std :: inserter '我會寫一個使用'operator []'的自定義函數。替代的2-liner雖然可能效率不高,但可以複製rhsItr,然後定期將lhsItr插入到副本中,然後交換。 – CashCow 2011-02-24 11:14:48

+1

@CashCow:與插入的自定義方法相比,我的方法的主要優點是括號運行在平均情況下O(lg n),而我發佈的代碼應該以線性時間運行,假設插入的執行很好,因爲暗示有附近的迭代器。 – templatetypedef 2011-02-24 11:23:02