Intersection of two `std::map`s
#include <map>
#include <utility>
template <typename KeyType, typename LeftValue, typename RightValue>
std::map<KeyType, std::pair<LeftValue, RightValue>>
IntersectMaps(const std::map<KeyType, LeftValue>& left,
const std::map<KeyType, RightValue>& right) {
std::map<KeyType, std::pair<LeftValue, RightValue>> result;
typename std::map<KeyType, LeftValue>::const_iterator il = left.begin();
typename std::map<KeyType, RightValue>::const_iterator ir = right.begin();
while (il != left.end() && ir != right.end()) {
if (il->first < ir->first)
++il;
else if (ir->first < il->first)
++ir;
else {
result.insert(std::make_pair(il->first, std::make_pair(il->second, ir->second)));
++il;
++ir;
}
}
return result;
}
I haven't tested this, or even compiled it... but it should be O(n). Because it's templated it should work with any two maps that share the same key type.
Intersection of two std::unordered_map
You could use std::set_intersection
to fill a new container containing the key
, value
pairs that exists in both maps. set_intersection
needs the ranges to be sorted (which is exactly what you won't get from an unordered_map
) so either, replace the unordered_map
s with map
or create temporary map
s (or temporary std::set<std::pair<int, int>>
s) before using set_intersection
.
I would recommend replacing your original unordered_map
s with ordered map
s for efficiency if you need intersections often:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <map>
#include <unordered_map>
#include <vector>
int main() {
std::map<int, int> mp1 {{1,0}, {2,0}, {3,0}};
std::map<int, int> mp2 {{0,0}, {2,0}, {3,0}};
// this can be unordered unless you plan to use it in an intersection later:
std::unordered_map<int, int> mp;
std::set_intersection(
mp1.begin(), mp1.end(),
mp2.begin(), mp2.end(),
std::inserter(mp, mp.begin())
);
for(auto[key, val] : mp) {
std::cout << key << ',' << val << '\n';
}
}
Possible output:
3,0
2,0
If you want to stay with unordered_map
s and to not have to create temporary set
s or map
s, you can just replace set_intersection
above with a manual filler:
const auto& [min, max] = std::minmax(mp1, mp2,
[](auto& a, auto& b) {
return a.size() < b.size();
});
for(auto& [key, value] : min) { // iterate over the smallest map
auto fi = max.find(key); // find in the bigger map
if(fi != max.end() && fi->second == value)
mp.emplace(key, value); // add the pair if you got a hit
}
The reason for iterating over the smallest map is to keep the number of find
operations down to a minimum. Consider a case where one map contains 1 element and the other 1000000 elements. You then want 1 lookup and not 1000000.
A more generic solution could be making a function template out of it:
template<
class Key,
class T,
class Hash = std::hash<Key>,
class KeyEqual = std::equal_to<Key>,
class Allocator = std::allocator< std::pair<const Key, T> >
>
auto unordered_map_intersection(
const std::unordered_map<Key,T,Hash,KeyEqual,Allocator>& mp1,
const std::unordered_map<Key,T,Hash,KeyEqual,Allocator>& mp2)
{
std::unordered_map<Key,T,Hash,KeyEqual,Allocator> mp;
const auto& [min, max] = std::minmax(mp1, mp2,
[](auto& a, auto& b) {
return a.size() < b.size();
});
for(auto& [key, value] : min) { // iterate over the smallest map
auto fi = max.find(key); // find in the bigger map
if(fi != max.end() && fi->second == value)
mp.emplace(key, value); // add the pair if you got a hit
}
return mp;
}
How do I get a set intersection of two std::unordered_map's?
The most straightforward implementation is:
MapType intersectFilter(const MapType& mapA, const MapType& mapFilter)
{
MapType result;
for (const auto& pair: mapA)
{
if (mapFilter.find(pair.first) != mapFilter.end())
result.insert(pair);
}
return result;
}
I've changed type of parameters to const references, since probably you don't want to copy the parameters.
Simultaneous Union and Intersection between two maps in C++
Add these two loops just after your main while loop.
while (it1 != Kmer1.cend()){
U += it1->second;
it1++;
}
while (it2 != Kmer2.cend()){
U += it2->second;
it2++;
}
Intersection of two unordered_maps
I know you don't want to hear it, but I'm going to say it anyway: you should cache the hash value on the instances so that hashing reduces to simple member lookup. If the instances are immutable (or at least, the parts that go into the hash function are immutable), then the easiest way to do this is to compute the hash in the constructor.
std::map and performance, intersecting sets
I figured something out: if I attach the debugger to either RELEASE or DEBUG builds (e.g. hit F5 in the IDE), then I get horrible times.
C++ Intersect two maps on keys, keep value of first map
You need to iterate map1
and map2
independently. You cannot use an iterator of map1
to manipulate another map (to erase
from map2
or to perform any other operations with map2
).
So the code should be something like this:
map<int, double> map1, map2;
map<int, CustomType> map3;
for (auto it = map1.cbegin(); it != map1.cend(); )
{
if ( map3.find(it->first) == map3.end() )
it = map1.erase(it);
else
++it;
}
for (auto it = map2.cbegin(); it != map2.cend(); )
{
if ( map3.find(it->first) == map3.end() )
it = map2.erase(it);
else
++it;
}
Using a map with set_intersection
MoneyMap map2;
map1.insert( MoneyPair( 3, mn[3] ) ); // (3)
map1.insert( MoneyPair( 4, mn[4] ) ); // (4)
map1.insert( MoneyPair( 5, mn[5] ) );
map1.insert( MoneyPair( 6, mn[6] ) );
map1.insert( MoneyPair( 7, mn[7] ) );
Unless this is a typo, you are just reinserting stuff into map1 instead of inserting into map2. I tested it out with the corrected code and it outputted "Intersection has 2 elements."
Related Topics
Simple For() Loop Benchmark Takes the Same Time with Any Loop Bound
How to Write an Agile Pimpl in C++
Opencv's Canny Edge Detection in C++
How to Increase Error Limit in Visual Studio
Opengl: Glgeterror() Returns Invalid Enum After Call to Glewinit()
Problem with Compiling Rinside Examples Under Windows
Win32 C/C++ Load Image from Memory Buffer
How to Differentiate (When Overloading) Between Prefix and Postfix Forms of Operator++? (C++)
How to Vertically Align Text in Edit Box
Why Do I See 400X Outlier Timings When Calling Clock_Gettime Repeatedly
Static Variable Initialization Over a Library
Why Openmp Under Ubuntu 12.04 Is Slower Than Serial Version
Std::Vector Calling Destructor Multiple Times During Push_Back