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)。