如何连接几个映射
How to concatenate few maps?
我有几个地图std::map< char, int >
First map:
a - 1
b - 2
c - 3
Second map:
a - 5
c - 6
e - 7
我想将它们连接到std::map< char, std::vector< int > >
中
a - 1 5
b - 2 0
c - 3 6
e - 0 7
做这件事最好的方法是什么?
首先想到的是std::merge
算法。不幸的是,源和目标范围的值类型不兼容,所以我们需要一些东西来转换它。Boost通过函数输出迭代器提供了一个很好的功能。分配给这个输出迭代器的任何内容都将作为参数传递给它所包装的一元函数。与lambdas一起,这是一个非常尖锐的问题:
#include <boost/function_output_iterator.hpp>
std::map<char, int> m1 { {'a',1}, {'b',2}, {'c',3} };
std::map<char, int> m2 { {'a',5}, {'c',6}, {'e',7} };
std::map<char, std::vector<int>> m3;
typedef std::map<char, int>::value_type source_type;
auto push_value =
[&m3](const source_type& p) { m3[p.first].push_back(p.second); };
std::merge(m1.begin(), m1.end(), m2.begin(), m2.end(),
boost::make_function_output_iterator(push_value));
这还不是我们想要的。m3
看起来像这样:
a - 1 5
b - 2
c - 3 6
e - 7
对于在m2
中但不在m1
中的关键帧,我们需要在向量的前面挤压一个零。在进行合并之前,我们可以使用set_difference
来完成此操作。我们需要使用自定义比较器,只比较地图的键:
auto push_zero =
[&m3](const source_type& p) { m3[p.first].push_back(0); };
auto cmp =
[](const source_type& p1, const source_type& p2) { return p1.first < p2.first; };
std::set_difference(m2.begin(), m2.end(), m1.begin(), m1.end(),
boost::make_function_output_iterator(push_zero), cmp);
m3
现在是:
a - 1 5
b - 2
c - 3 6
e - 0 7
在第三步中,我们为m1
中但不在m2
中的密钥添加一个零:
std::set_difference(m1.begin(), m1.end(), m2.begin(), m2.end(),
boost::make_function_output_iterator(push_zero), cmp);
现在我们有了我们想要的:
a - 1 5
b - 2 0
c - 3 6
e - 0 7
请参阅LiveWorkspace上的完整示例。
最简单的方法是首先在目标映射中添加所有键。然后,对于目标映射中的每个关键字,添加第一个映射中的相应值,如果找不到关键字,则添加零。然后对第二个贴图执行相同操作。
像这样的助手函数怎么样:
void one_map ( const std::map <char, int> &source, std::map<char, std::vector<int> > &dest, size_t idx )
for ( auto const &p : source )
dest [ p.first ] [ idx ] += 1;
}
void fill_map ( const std::map <char, int> &source, std::map<char, std::vector<int> &dest , const std::vector<int> &zeroes ) {
for ( auto const &p : source )
if ( !dest.find ( p.first ))
dest [ p.first ] = zeroes;
}
然后你可以写:
std::vector<int> z (3, 0); // three zeros
fill_map ( a, dest, z );
fill_map ( b, dest, z );
fill_map ( c, dest, z );
one_map ( a, dest, 0 );
one_map ( b, dest, 1 );
one_map ( c, dest, 2 );
值得一提的是,这里有一个简单的无提升解决方案,它可能运行得更快(不是在大O中,而是在总迭代次数中):
std::map<char,int>::iterator i,j;
i = m1.begin(); j = m2.begin();
while (i!=m1.end() || j!=m2.end()) {
if (j==m2.end() || (i!=m1.end()&&(i->first < j->first))) {
m3[i->first].push_back(i->second);
m3[i->first].push_back(0);
i++;
} else if (i==m1.end() || (i->first > j->first)) {
m3[j->first].push_back(0);
m3[j->first].push_back(j->second);
j++;
} else if (i->first == j->first) {
m3[i->first].push_back(i->second);
m3[j->first].push_back(j->second);
i++;j++;
}
}
可能可以简化以减少代码行数,因为push_backs每次执行3次(3种不同的情况)。。。。
这里的运行时间是(m1中的#)+(m2中的#")-(两者中的#")。在所有的可能性中,这大致等于一个单集差(或一个单合并)。
Liveworkspace
相关文章:
- 为我的 c++ 类介绍制作一个三角形分类器.我有几个问题
- 使用 make 编译 MPI,几个命名空间错误,例如"错误:未知类型名称'使用'?
- 如何返回或护理项目清单基于几个类别
- 我们如何在文本文件中找到C++中的几个单词?
- 关于 std::bitset 构造函数的几个问题?
- 几个 Nt 函数在 Windows 7 x32 上返回STATUS_WAIT_0
- std::stoi 只转换前几个字符
- C++ 通过接口使用从其他几个类继承的类
- 在矢量中使用擦除时双重释放或损坏(快速顶部).如何擦除一个矢量的几个项目知道它们的索引?
- 如何遍历几个每小时一次的根(.root)文件,并将它们组合成更大的每日数据.root文件?
- 我有几个关于参考变量的问题
- 如何将几个变量复制到其他变量
- 如何在新设计中迁移需要几个额外参数的函数
- 多线程.如果我使用信号量,我可以在开始时创建很多线程还是应该只有几个线程?
- 如何在几个空行后打印文件中的输出
- recvfrom 只收到几个数据包,之后它进入等待状态
- 使用 std::vector<std::future<int>> 和 std::async 启动几个线程时中止
- C++ 两个线程,共享几个整数变量
- 将几个大文件映射到内存
- 如何连接几个映射