如何将两个STL映射合并为一个?它们具有相同的键和值类型(map<string, string>
)。如果按键重叠,我想优先考虑其中一张地图。
Answers:
假设您要保留中的元素mapA
,并合并mapB
其中没有关键字的元素mapA
:
mapA.insert(mapB.begin(), mapB.end())
我想会做你想要的。
(编辑:如果您使用的是C ++ 17或更高版本,请考虑以下答案:https : //stackoverflow.com/a/56594603/118150)
工作示例:
#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
value_comp()
,但标准不强制要求)。
如果要将条目从一个地图复制到另一个地图,可以使用std::map
的insert
:
targetMap.insert(sourceMap.begin(), sourceMap.end());
但是请注意,insert
如果元素的键已经在targetMap中,则不会更新元素;这些项目将保持原样。要覆盖元素,必须显式复制,例如:
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
的条目。
如John Perry的回答中所述,由于C ++ 17 std::map
提供了merge()
成员函数。如下面的示例所示,该merge()
函数对目标地图产生的结果与jkerian基于using的解决方案相同insert()
,这是我从jkerian借来的。我刚刚使用一些C ++ 11和C ++ 17功能(例如using
类型别名,具有结构化绑定的基于范围的for循环和列表初始化)更新了代码:
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
。
注意:map<int, int>
为了方便起见,我重用了jkerian的示例,该示例merge()
也适用于您map<string, string>
。
根据ISO / IEC 14882:2003第23.1.2节,表69,表达式a.insert(i,j):
上一条: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的“值”。