C++ 合并两个映射,对C+中相同键的值求和+;
我有两个C++ 合并两个映射,对C+中相同键的值求和+;,c++,merge,maps,C++,Merge,Maps,我有两个std::map映射,希望将它们合并到第三个映射中,如下所示: 如果在两个映射中都找到相同的键,则在第三个映射中创建一个具有相同键和一个值的对,该值表示第一个映射和第二个映射的值之和,否则只需将一个对复制到第三个映射。 我怀疑用std::acculate可以做到这一点,但我对它的理解还不够透彻。我认为要找到一个适合这个目的的std::algorithm并不容易(如果不是不可能的话) 最简单的方法是首先将map1复制到map\u结果 std::map<int,int> map_
std::map
映射,希望将它们合并到第三个映射中,如下所示:
如果在两个映射中都找到相同的键,则在第三个映射中创建一个具有相同键和一个值的对,该值表示第一个映射和第二个映射的值之和,否则只需将一个对复制到第三个映射。
我怀疑用
std::acculate
可以做到这一点,但我对它的理解还不够透彻。我认为要找到一个适合这个目的的std::algorithm
并不容易(如果不是不可能的话)
最简单的方法是首先将map1
复制到map\u结果
std::map<int,int> map_result( map1 );
for (auto it=map2.begin(); it!=map2.end(); ++it) {
if ( map_result[it->first] )
map_result[it->first] += it->second;
else
map_result[it->first] = it->second;
}
然后遍历map2
,查看map\u结果中是否存在任何key
,然后添加值
,否则将key\u值
对添加到map\u结果
std::map<int,int> map_result( map1 );
for (auto it=map2.begin(); it!=map2.end(); ++it) {
if ( map_result[it->first] )
map_result[it->first] += it->second;
else
map_result[it->first] = it->second;
}
std::map\u结果(map1);
对于(自动it=map2.begin();it!=map2.end();++it){
if(映射结果[it->first])
映射结果[it->first]+=it->second;
其他的
映射结果[it->first]=it->second;
}
一个受std::set\u union
启发的过于通用的解决方案。与第一个建议的答案不同,它应该在O(n)而不是O(n log n)中运行
编辑:由于插入到最终地图中,它仍然是O(n log n)
#include <map>
#include <iostream>
#include <iterator>
#include <algorithm>
template<class InputIterT1, class InputIterT2, class OutputIterT, class Comparator, class Func>
OutputIterT merge_apply(
InputIterT1 first1, InputIterT1 last1,
InputIterT2 first2, InputIterT2 last2,
OutputIterT result, Comparator comp, Func func) {
while (true)
{
if (first1 == last1) return std::copy(first2, last2, result);
if (first2 == last2) return std::copy(first1, last1, result);
if (comp(*first1, *first2) < 0) {
*result = *first1;
++first1;
} else if (comp(*first1, *first2) > 0) {
*result = *first2;
++first2;
} else {
*result = func(*first1, *first2);
++first1;
++first2;
}
++result;
}
}
template<class T>
int compare_first(T a, T b) {
return a.first - b.first;
}
template<class T>
T sum_pairs(T a, T b) {
return std::make_pair(a.first, a.second + b.second);
}
using namespace std;
int main(int argc, char **argv) {
map<int,int> a,b,c;
a[1] = 10;
a[2] = 11;
b[2] = 100;
b[3] = 101;
merge_apply(a.begin(), a.end(), b.begin(), b.end(), inserter(c, c.begin()),
compare_first<pair<int, int> >, sum_pairs<pair<int, int> >);
for (auto item : c)
cout << item.first << " " << item.second << endl;
}
#包括
#包括
#包括
#包括
模板
输出合并应用(
InputIterT1 first1,InputIterT1 last1,
InputIterT2 first2,InputIterT2 last2,
输出结果,比较器比较,函数(Func){
while(true)
{
if(first1==last1)返回std::copy(first2,last2,result);
if(first2==last2)返回std::copy(first1,last1,result);
如果(comp(*first1,*first2)<0){
*结果=*first1;
++第一个1;
}否则如果(comp(*first1,*first2)>0){
*结果=*first2;
++前2名;
}否则{
*结果=func(*first1,*first2);
++第一个1;
++前2名;
}
++结果;
}
}
模板
int比较_优先(ta,tb){
返回a.first-b.first;
}
模板
T和对(ta,tb){
返回std::make_对(a.first,a.second+b.second);
}
使用名称空间std;
int main(int argc,字符**argv){
地图a、b、c;
a[1]=10;
a[2]=11;
b[2]=100;
b[3]=101;
合并应用(a.begin(),a.end(),b.begin(),b.end(),插入器(c,c.begin()),
首先比较_,求和_对);
用于(自动项目:c)
cout下面是一个如何使用std::acculate完成任务的示例
#include <iostream>
#include <map>
#include <numeric>
int main()
{
std::map<int, int> m1 = { { 1, 1 }, { 2, 2 }, { 3, 3 }, { 4, 4 } };
std::map<int, int> m2 = { { 2, 5 }, { 3, 1 }, { 5, 5 } };
for ( const auto &p : m1 )
{
std::cout << "{ " << p.first << ", " << p.second << " } ";
}
std::cout << std::endl;
for ( const auto &p : m2 )
{
std::cout << "{ " << p.first << ", " << p.second << " } ";
}
std::cout << std::endl;
std::map<int, int> m3 = std::accumulate( m1.begin(), m1.end(), std::map<int, int>(),
[]( std::map<int, int> &m, const std::pair<const int, int> &p )
{
return ( m[p.first] +=p.second, m );
} );
m3 = std::accumulate( m2.begin(), m2.end(), m3,
[]( std::map<int, int> &m, const std::pair<const int, int> &p )
{
return ( m[p.first] +=p.second, m );
} );
for ( const auto &p : m3 )
{
std::cout << "{ " << p.first << ", " << p.second << " } ";
}
std::cout << std::endl;
return 0;
}
事实上,只有第二个映射需要使用std::acculate。第一个映射可以简单地复制或分配给m3
比如说
std::map<int, int> m3 = m1;
m3 = std::accumulate( m2.begin(), m2.end(), m3,
[]( std::map<int, int> &m, const std::pair<const int, int> &p )
{
return ( m[p.first] +=p.second, m );
} );
std::map m3=m1;
m3=std::累加(m2.begin()、m2.end()、m3、,
[](标准::映射与建模,常数标准::配对与编程)
{
返回值(m[p.first]+=p.second,m);
} );
我应该写我自己的函数来做这件事吗?我想我明白了。谢谢这也运行在O(n log n)中,不是吗?@ales\t,似乎是这样。好吧,我要说它使用std::accumulate
和lambdas,我自己也不知道如何将这两个函数一起使用。所以,感谢演示。只需注意:这仍然会在O(n.log n)中运行
如果输出容器是一个map
我们可以使用std::unordered\u map
容器而不是std::map
使它在O(n)时间运行。如果我们在元素插入时使用提示,我们可以在std::map中在O(n)时间运行它。元素是按升序插入的,因此提示将始终映射到map.end()(C++11)。