2つのSTLマップを1つにマージするにはどうすればよいですか?両方とも同じキーと値のタイプ(map<string, string>
)。キーが重複している場合は、いずれかのマップを優先します。
mapA
の要素を保持し、mapB
にキーがないmapA
の要素をマージするとします。
mapA.insert(mapB.begin(), mapB.end())
あなたが望むことをするでしょう。
作業例:
#include <iostream>
#include <map>
void printIt(std::map<int,int> m) {
for(std::map<int,int>::iterator it=m.begin();it!=m.end();++it)
std::cout << it->first<<":"<<it->second<<" ";
std::cout << "\n";
}
int main() {
std::map<int,int> foo,bar;
foo[1] = 11; foo[2] = 12; foo[3] = 13;
bar[2] = 20; bar[3] = 30; bar[4] = 40;
printIt(foo);
printIt(bar);
foo.insert(bar.begin(),bar.end());
printIt(foo);
return 0;
}
出力:
:!./insert
1:11 2:12 3:13
2:20 3:30 4:40
1:11 2:12 3:13 4:40
あるマップから別のマップにエントリをコピーする場合は、std::map
のinsert
:
targetMap.insert(sourceMap.begin(), sourceMap.end());
ただし、キーがすでにtargetMapにある場合、insert
は要素を更新しないことに注意してください。それらのアイテムはそのまま残されます。要素を上書きするには、明示的にコピーする必要があります。例:
for(auto& it : sourceMap)
{
targetMap[it.first] = it.second;
}
sourceMap
のデータを失うことを気にしない場合、コピーと上書きを実現する別の方法は、ターゲットをソースにinsert
し、std::swap
結果:
sourceMap.insert(targetMap.begin(), targetMap.end());
std::swap(sourceMap, targetMap);
スワップ後、sourceMap
にはtargetMap
の古いデータが含まれ、targetMap
はsourceMap
のエントリを優先して、2つのマップのマージになります。
C++ 17以降、マップには merge()
メソッドがあることに注意してください。
ISO/IEC 14882:2003、セクション23.1.2、表69、式a.insert(i、j)によると:
pre:i、jはaへの反復子ではありません。一意のキーを持つコンテナにその要素のキーに相当するキーを持つ要素がない場合にのみ、範囲[i、j)から各要素を挿入します。
Std :: mapはこの制限に従う必要があるため、あるマップの「値」を別のマップよりも優先させる場合は、マップに挿入する必要があります。例えば、
std::map<int, int> goodKeys;
std::map<int, int> betterKeys;
betterKeys.insert(goodKeys.begin(), goodKeys.end());
したがって、goodKeysおよびbetterKeysに同等のキーがある場合、betterKeysの「値」は保持されます。
John Perry's answer で述べたように、 C++ 17std::map
は merge()
を提供するため メンバー関数。 merge()
関数は、以下からわかるように、 insert()
の使用に基づいて jkerianの解 と同じ結果をターゲットマップに対して生成します。例、jkerianから借りました。 C++ 11 およびC++ 17の機能( using
type alias 、 range-based forループ with 構造化バインディング 、および リスト初期化 ):
using mymap = std::map<int, int>;
void printIt(const mymap& m) {
for (auto const &[k, v] : m)
std::cout << k << ":" << v << " ";
std::cout << std::endl;
}
int main() {
mymap foo{ {1, 11}, {2, 12}, {3, 13} };
mymap bar{ {2, 20}, {3, 30}, {4, 40} };
printIt(foo);
printIt(bar);
foo.merge(bar);
printIt(foo);
return 0;
}
出力:
1:11 2:12 3:13
2:20 3:30 4:40
1:11 2:12 3:13 4:40
ご覧のように、merge()
は、キーがオーバーラップするときにターゲットマップfoo
を優先します。逆にしたい場合は、bar.merge(foo);
を呼び出す必要があります。
ただし、ソースマップの処理に関してinsert()
とmerge()
の使用には違いがあります。 insert()
関数は新しいエントリをターゲットマップに追加し、merge()
関数はエントリをソースマップから移動します。つまり、上記の例では、insert()
はbar
を変更しませんが、merge()
はbar
から4:40
を削除するため、2:20
と3:30
はbar
に残ります。
注:簡潔にするためにmap<int, int>
を使用するjkerianの例を再利用しましたが、merge()
はmap<string, string>
でも機能します。