如何将两个STL地图合并为一个?它们都具有相同的键值类型(map)。如果键有重叠,我想优先考虑其中一个地图。
答案 0 :(得分:110)
假设您要保留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
答案 1 :(得分:28)
如果您要将条目从一个地图复制到另一个地图,可以使用std::map
的{{1}}:
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
条目。
答案 2 :(得分:10)
请注意,自C ++ 17以来,地图有merge()
方法。
答案 3 :(得分:3)
根据ISO / IEC 14882:2003,第23.1.2节,表69,表达式a.insert(i,j):
pre:i,j不是迭代器。插入范围中的每个元素 [i,j]当且仅当没有元素与key相当于 具有唯一键的容器中该元素的键;
由于std :: map必须遵循此限制,如果您想优先考虑从一个地图到另一个地图的“值”,则应插入其中。例如,
std::map<int, int> goodKeys;
std::map<int, int> betterKeys;
betterKeys.insert(goodKeys.begin(), goodKeys.end());
因此,如果goodKeys和betterKeys中存在任何等效键,则将保留betterKeys的“值”。
答案 4 :(得分:0)
如John Perry's answer中所述,由于C++17 std::map
提供了merge()
成员函数。 merge()
函数基于jkerian's solution使用insert()
为目标地图生成与C++11相同的结果,如下面的示例所示,我是从jkerian借来的。我刚刚使用一些using
type alias和C ++ 17功能(例如range-based for loop,structured binding和list initialization和Code on Coliru)更新了代码:
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()
会从4:40
中删除bar
,因此只有2:20
和3:30
保留在bar
中。
注意:为简洁起见,我重用了jkerian的示例,该示例使用map<int, int>
,但是merge()
也适用于您的map<string, string>
。