Introduction
We have std::map<key,std::vector<std::string>> m;
where the key
is represented by std::tuple<std::string, std::string,std::string>
. But there is a constraint, the last field of the tuple can be an empty string. If the last element of the tuple is an empty string then we should merge it with the with elements of the map having same first and second elements.
Input:
o1("1","1","1")
o2("1","1","1")
o3("1","1","1")
o4("2","2","2")
o5("2","2","2")
o6("2","2","")
o7("2","2","")
Output:
Key: 1 1 1 ==> size: 3
Key: 2 2 2 ==> size: 4
Indeed, (1,1,1)
are grouped together and (2,2,2)
, (2,2,"")
are grouped together. I have to do the merge in 2 steps and I have to use 2 maps to do that.
Is there a way to improve how I merge the keys together?
#include <iostream>
#include <tuple>
#include <map>
#include <vector>
#include <algorithm>
using key = std::tuple<std::string, std::string,std::string>;
/* Object we want to merge */
struct Object {
Object(const std::string& x, const std::string& y, const std::string& z ):_x(x),_y(y),_z(z){}
std::string _x;
std::string _y;
std::string _z;
/* This object has more data members */
};
std::map<key,std::vector<Object>> mergeObjects(const std::vector<Object> &v) {
/* Holds the objects without empty elements */
std::map<key,std::vector<Object>> m;
/* Holds the objects with last empty element */
std::map<key,std::vector<Object>> m1;
/* Step 1: Fill maps m and m1 based on whether z is empty or not*/
for(const auto &o:v) {
/* if "z" is empty then put "o" in m1 else in m */
if(o._z.empty()) {
m1[std::make_tuple(o._x, o._y, o._z)].push_back(o);
} else {
m[std::make_tuple(o._x, o._y, o._z)].push_back(o);
}
}
/* Step 2: Merge elements. Find elements of m1 in m that have the same first and second elements */
for(const auto& [k,v]: m1){
auto[x, y, z] = k;
/* Find first occurrence of k in m */
auto it = std::find_if(m.begin(), m.end(),[&](const std::pair<key, std::vector<Object>>& k1){
auto[x1, y1, z1] = k1.first;
return (x == x1 and y == y1);
});
/* If key found then merge and concatenate vectors*/
if(it != m.end()) {
it->second.insert(it->second.end(),v.begin(), v.end());
}
}
return m;
}
int main() {
/* What we receice as input */
Object o1("1","1","1"), o2("1","1","1"), o3("1","1","1"), o4("2","2","2"), o5("2","2","2"), o6("2","2",""),o7("2","2","");
std::vector<Object> v = {o1, o2, o3, o4, o5, o6, o7};
/* Merge Objects together if applicable */
std::map<key,std::vector<Object>> m = mergeObjects(v);
/* Print Merged Objects */
for(const auto&[k,v]: m){
std::cout << "Key: " << std::get<0>(k) <<" " << std::get<1>(k) <<" "<<std::get<2>(k) <<" ===> Size: "<< v.size() << std::endl;
}
return 0;
}