如何合并2个std::映射,并在第三个映射中输出结果
How to merge 2 std::maps, and output the result in a 3rd map
编辑原始问题,因为我想问关于std::map
而不是std::vector
的问题。我的错误。很抱歉
我的数据实际上在2个std::map
s中。我想将两个映射合并到第三个映射中。
我的第一个和第二个映射包含具有相同关键字的条目。所以我也想将这些键下的数据合并到我的第三个映射中。
那么,如果我使用std::merge
,我会丢失第一个或第二个映射公共条目中的数据吗?正如我所提到的,两个地图中都有共同的数据(值)?
顺序容器的信息
如果对vector
(或其他顺序容器,如list
或deque
)进行了排序,则可以使用std::set_union
。有一个std::merge
,以防您想保存重复的
从链接页面获取的代码:
#include <vector>
#include <iostream>
#include <algorithm>
#include <iterator>
int main()
{
std::vector<int> v1 = {1, 2, 3, 4, 5};
std::vector<int> v2 = { 3, 4, 5, 6, 7};
std::vector<int> dest1;
std::set_union(v1.begin(), v1.end(),
v2.begin(), v2.end(),
std::back_inserter(dest1));
for (const auto &i : dest1) {
std::cout << i << ' ';
}
std::cout << 'n';
}
输出:1 2 3 4 5 6 7
关联容器的信息
您可以使用insert
方法向map
(或set
及其无序对应项)添加唯一密钥。原始映射中已经存在的任何密钥都不会被替换(在multiset
和multimap
中,将添加重复的密钥,如果应该避免,请使用之前讨论过的set_union
)。
映射示例(忽略具有重复键的条目):
#include <map>
#include <iostream>
int main()
{
std::map<int, int> v1 = {{1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1}};
std::map<int, int> v2 = { {3, 2}, {4, 2}, {5, 2}, {6, 2}, {7, 2}};
std::map<int, int> dest1 = v1;
dest1.insert(v2.begin(), v2.end());
for (const auto &i : dest1) {
std::cout << i.first << ':' << i.second << ' ';
}
std::cout << 'n';
}
输出(第一个数字是关键,第二个数字——它来自哪个地图):1:1 2:1 3:1 4:1 5:1 6:2 7:2
如果切换映射(在开始时将dest1
设置为v2
的副本,并插入v1
的值),则输出将为:1:1 2:1 3:2 4:2 5:2 6:2 7:2
多映射示例(两个映射中的条目都保留):
#include <map>
#include <iostream>
int main()
{
std::map<int, int> v1 = {{1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1}};
std::map<int, int> v2 = { {3, 2}, {4, 2}, {5, 2}, {6, 2}, {7, 2}};
std::multimap<int, int> dest1 {v1.begin(), v1.end()};
dest1.insert(v2.begin(), v2.end());
for (const auto &i : dest1) {
std::cout << i.first << ':' << i.second << ' ';
}
std::cout << 'n';
}
输出:1:1 2:1 3:1 3:2 4:1 4:2 5:1 5:2 6:2 7:2
请注意,不能像使用贴图那样使用multimap
。例如,operator[]
不可用。您需要使用insert
来添加条目,并使用lower_bound
或equal_range
成员函数来提取条目。
这就是std::merge
的作用:
std::merge(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(v3));
我相信您想要的是既能合并映射,又能合并映射的内容。
template<class Map, class Merge>
Map careful_merge( Map lhs, Map const& rhs, Merge&& merge ) {
for (auto&& rhs_entry : rhs) {
auto lhs_it = lhs.find(rhs_entry.first);
if (lhs_it == lhs.end()) {
lhs.insert( rhs_entry );
continue;
}
auto& lhs_value = lhs_it.second;
lhs_value = merge(std::move(lhs_value), rhs.second);
}
return lhs;
}
这是一个助手函数,它接受两个关联容器,如果值在两个容器中,则调用merge
。
假设您有一个std::map< std::string, std::vector<int> >
,并希望合并它们,以便结果将映射的附加到向量。然后:
using my_map = std::map< std::string, std::vector<int> >;
my_map a, b; // fill these somehow.
my_map result = careful_merge( a, b,
[](std::vector<int> lhs, std::vector<int> const& rhs ) {
lhs.insert(lhs.end(), rhs.begin(), rhs.end());
return std::move(lhs);
}
);
我们完了。
左侧或右侧唯一的条目永远不会合并,只是逐字复制到输出中。
假定有效的移动语义。
它既适用于有序映射,也适用于无序映射。它不适用于套装。我建议不要在多地图上使用它,即使它有效(我不确定),因为它不是为他们设计的。
请注意,从C++17开始,现在有一个std::map::merge(other_map)
方法。
请参阅https://en.cppreference.com/w/cpp/container/map/merge
- 模板-模板参数推导:三个不同的编译器三种不同的行为
- 在 2D 向量中使用第三个 [ ] 有什么意义?
- 如何通过按下第三个窗口中的按钮,将QString从一个窗口获取到另一个窗口
- 如何知道n!是否可以表示为三个连续数字的乘法?
- 我有三个 getline,但是一旦编译,输入就太多了
- 我遇到了黑客排名中的问题"TWO STRINGS"的三个测试用例的分段错误。原因是什么?
- 有没有更好的方法对C++中的三个整数进行排序?
- 如何检查第三个 API 是否在 Linux 中为 c/c++ 程序创建了一个新线程?
- 为什么 getch 在按下函数或箭头键时返回三个值?
- 使用三个数字比较器进行排序
- 我想在C++代码中比较这三个术语
- 我的动态链接队列在同一输出流中调用时不正确地输出三个返回函数
- 我该如何编码,使计算机知道两个名称条目和三个名称条目之间的区别
- 为什么我需要三个嵌套的大括号来调用赋值运算符,将const引用到二维数组
- 如何通过通用引用或std::forward将这三个c++模板函数合并为一个
- 首先处理第二个和第三个堆与第一个和第二个堆之间的逻辑差异
- 异常处理:如果用户输入不是三个特定字符之一
- 以三个无符号字符为关键字的无序映射
- 如何合并2个std::映射,并在第三个映射中输出结果
- c++中嵌套三个映射Vs单独映射的性能