I have two multimaps.i would like to create a new multimap which has the common key-value pairs in the given those two multimaps:
for eg:
#include &l
Use the std::set_intersection
function template from <algorithm>
std::multimap<T1, T2> newMap;
std::set_intersection(map1.begin(), map1.end(),
map2.begin(), map2.end(),
std::inserter(newMap, newMap.begin());
Edit Yeah, apparently this doesn't work for a multimap as it would for a map. I suggest the following:
std::multimap<T1, T2> newMap;
std::vector<std::multimap<T1, T2>::value_type> v1(map1.begin(), map1.end());
std::sort(v1.begin(), v1.end());
std::vector<std::multimap<T1, T2>::value_type> v2(map2.begin(), map2.end());
std::sort(v2.begin(), v2.end());
std::set_intersection(v1.begin(), v1.end(),
v2.begin(), v2.end(),
std::inserter(newMap, newMap.begin());
As an alternative solution to Armen's (which is excellent), here's a way to copy and sort at the same time:
typedef std::multimap<std::string, std::string> map_type;
map_type m, n, result;
m.insert(std::make_pair("1-2", "1-1"));
// --------8<--------
n.insert(std::make_pair("1-3", "21-2"));
// --------8<--------
std::set<map_type::value_type> s1(m.begin(), m.end());
std::set<map_type::value_type> s2(n.begin(), n.end());
std::set_intersection(s1.begin(), s1.end(),
s2.begin(), s2.end(),
std::inserter(result, result.end()));
intersection
============
1-2 1-1
1-2 1-2
1-3 2-1
1-3 21-2
To get the elements that are only in m
:
result.clear();
std::set_difference(s1.begin(), s1.end(),
s2.begin(), s2.end(),
std::inserter(result, result.end()));
And only in n
:
result.clear();
std::set_difference(s2.begin(), s2.end(),
s1.begin(), s1.end(),
std::inserter(result, result.end()));
See it run.
Since you've copied m
and n
(into s1
and s2
) at the time of doing the set_difference(), you could clear()
these and insert into them instead of result
.
For fun, here's the direct algorithm, which moves common elements into a new multimap, changing the original maps. You will recognize the standard "set intersection" algorithm for sorted ranges on the outer loop (concerning first
); and since we cannot assume anything about the mapped values, the inner loop (concerning second
) is a linear search over the mapped values to find equals.
template <typename T>
T move_common(T & a, T & b)
{
typename T::const_iterator it1 = a.cbegin(), iend = a.cend(), jt1 = b.cbegin(), jend = b.cend();
T result;
while (it1 != iend && jt1 != jend)
{
if (it1->first < jt1->first)
{
++it1;
}
else if (jt1->first < it1->first)
{
++jt1;
}
else
{
typename T::const_iterator it2 = it1;
while (it2 != iend && it2->first == it1->first)
{
typename T::const_iterator jt2 = jt1;
while (jt2 != jend && jt2->first == jt1->first)
{
if (jt2->second == it2->second)
{
result.insert(*it2);
if (it2 == it1) { a.erase(it1++); it2 = it1; } else { a.erase(it2++); }
if (jt2 == jt1) { b.erase(jt1++); } else { b.erase(jt2); }
break;
}
else
{
++jt2;
if (jt2 == jend || jt2->first != jt1->first) { ++it2; break; }
}
}
}
it1 = it2;
}
}
return result;
}
Result:
common = [(1-2, 1-1), (1-2, 1-2), (1-3, 2-1), (1-3, 21-2)]
n after = [(1-2, 1-3), (1-2, 1-4), (1-3, 21-1)]
m after = [(1-2, 1-5), (1-2, 1-7), (1-3, 21-4)]