聚合 std::multimap 中相同键的值并存储在 std::map 中

Aggregate values of same key in std::multimap and store in std::map

我本质上是想通过键对multimap的元素进行分组,并获得新的数据结构作为一个map。

多图:

std::multimap<std::string,std::vector<int>> multiMap;
 
    VecA VecB
ABC  10  30
ABC  10  30
DEF  20  20

所需的输出:

std::map<std::string,std::vector<int>> map;

   VecA VecB
ABC 20  60
DEF 20  20

以下代码适用于 std::multimap<std::string,int>

std::vector<std::string> a = {ABC,ABC,DEF,GHI};
std::vector<int> b = {10,20,30,40};
    
std::multimap<std::string,int> multiMap;

for (int i = 0; i < a.size(); i++)
{
  multiMap.insert(std::pair<std::string,int >(a[i], b[i]));
}

std::map<std::string,int> map;

std::for_each
(
multiMap.begin(),
multiMap.end(),
[&map] (auto const & i) 
 {
   map[i.first] += i.second;
 }
);

我无法更改上述块第 19 行的代码(即在 lambda 函数中)以在 std::multimap<std::string,std::vector<int>> 的情况下扩展到 std::map<std::string,std::vector<int>>

如果你想使用算术运算符

使用valarray

演示:https://wandbox.org/permlink/SAnHNKNZ0UufqZsN

#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <valarray>
#include <numeric>

int main()
{

    using key_type = std::valarray<int>;
    key_type b = {10,20,30,40};
    
    auto containerToStr = [](const auto& cont)
    {
       return std::accumulate(std::begin(cont), std::end(cont), std::string{}, [](const auto& str, const auto& val){
           return str + " " + std::to_string(val);
       });
    };

    
    std::multimap<std::string,key_type> multiMap;
    std::vector<std::string> a = {"ABC","ABC","DEF","GHI"};
    for (size_t i = 0; i < a.size(); i++)
    {
        multiMap.insert(std::pair<std::string,key_type >(a[i], b));
    }

    std::cout << "Before sum" << std::endl;
    for (const auto& p : multiMap)
        std::cout << p.first << " " << containerToStr(p.second) << std::endl;
    std::cout << std::endl;
    
    std::map<std::string,key_type> map;


    std::for_each( multiMap.begin(), multiMap.end(), [&map] (auto const & i) 
        {
            //  map[i.first] += i.second; // caution  map[i.first] create an empty key_type 
            if ( map.count(i.first) > 0)
            {
                map.at(i.first) += i.second;
            }
            else
            {
                map.insert({i.first, i.second});
            }
        }
    );

    std::cout << "After sum" << std::endl;
    for (const auto& p : map)
        std::cout << p.first << " " << containerToStr(p.second) << std::endl;
}

如果你想使用std::vector

定义求和函数。

演示:https://wandbox.org/permlink/FteFkLfwQh0P4wzp

#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <numeric>

int main()
{

    using key_type = std::vector<int>;
    key_type b = {10,20,30,40};
    
    auto containerToStr = [](const auto& cont)
    {
       return std::accumulate(std::begin(cont), std::end(cont), std::string{}, [](const auto& str, const auto& val){
           return str + " " + std::to_string(val);
       });
    };

    
    std::multimap<std::string,key_type> multiMap;
    std::vector<std::string> a = {"ABC","ABC","DEF","GHI"};
    for (size_t i = 0; i < a.size(); i++)
    {
        multiMap.insert(std::pair<std::string,key_type >(a[i], b));
    }

    std::cout << "Before sum" << std::endl;
    for (const auto& p : multiMap)
        std::cout << p.first << " " << containerToStr(p.second) << std::endl;
    std::cout << std::endl;
    
    std::map<std::string,key_type> map;

    // Warning : naive function, to rework
    auto your_sum = [](const auto& cont1, const auto& cont2)
    {
        key_type result;
        const auto smaller = std::min(cont1.size(), cont2.size());
        for ( size_t i = 0 ; i < smaller; i++)
        {
              result.push_back(cont1[i]+cont2[i]);  
        }
        return result;
    };

    std::for_each( multiMap.begin(), multiMap.end(), [&map,&your_sum] (auto const & i) 
        {
            //  map[i.first] += i.second; // caution  map[i.first] create an empty key_type 
            if ( map.count(i.first) > 0)
            {
                map.at(i.first) = your_sum(i.second, map.at(i.first));
            }
            else
            {
                map.insert({i.first, i.second});
            }
        }
    );

    std::cout << "After sum" << std::endl;
    for (const auto& p : map)
        std::cout << p.first << " " << containerToStr(p.second) << std::endl;
}