snazziii
snazziii

Reputation: 491

How do I find all the keys common in 2 maps?

I have 3 maps:

map<string, vector<int> > map1
map<string, vector<int> > map2
map<string, vector<int> > map3

I need to create a third map with all the strings existing in both map1 and map2 with their corresponding vectors. Thing is, even if the strings are same, their vectors can be different and i have to append all the vectors from both the common strings into 1 vector. This is what I'm trying but I'm kind of lost:

for(map<string, vector<int> >::iterator it1=map1.begin(); it1 != map1.end(); it1++)
{
    string name = (*it1).first;
    for(map<string, vector<int> >::iterator it2=map2.begin(); it2 != map2.end(); it2++)
    {
        string name2 = (*it2).first;
        if (name == name2)
        {
            map3[name2] = (*it2).second;

        }
    }
}

Thanks so much for your help!!

Upvotes: 4

Views: 2860

Answers (3)

Blastfurnace
Blastfurnace

Reputation: 18652

Since the maps are ordered you can do this in linear time. This is one possible way to do the task:

#include <map>
#include <string>
#include <vector>

typedef std::vector<int> vec_t;
typedef std::map<std::string, vec_t> map_t;
typedef map_t::const_iterator iter_t;

int main()
{
    map_t map1, map2, map3;

    iter_t it1 = map1.begin();
    iter_t it2 = map2.begin();

    while (it1 != map1.end() && it2 != map2.end()) {
        if (it1->first < it2->first) {
            ++it1;
        } else if (it2->first < it1->first) {
            ++it2;
        } else { // equal keys
            vec_t temp(it1->second);
            temp.insert(temp.end(), it2->second.begin(), it2->second.end());
            map3[it1->first].swap(temp); // swap contents to new map entry
            ++it1;
            ++it2;
        }
    }
}

Note that this assumes the map key ordering is the default less<Key>.

Upvotes: 4

Asha
Asha

Reputation: 11232

You can do

#include <algorithm>  // for std::copy
#include <iterator>   // for std::back_inserter
#include <map>
...

for(auto it = map1.begin(); it != map1.end(); ++it)
{
   auto fit = map2.find(it->first);
   if(fit != map2.end()
   {
      map3[it->first] = it->second;
      std::copy(fit->second.begin(), fit->second.end(), std::back_inserter(map3[it->first]));
   }
}

Upvotes: 2

Dave S
Dave S

Reputation: 21058

One solution is

map3 = map1;
typedef map<string, vector<int> > map_type;

for(map_type::iterator itr = map2.begin(); itr != map2.end(); ++itr)
{
    vector<int>& ref = map3[itr->first];
    ref.insert(ref.end(), itr->second.begin(), itr->second.end());
}

This first copies all entries from the first map into the destination. It then, for each entry in the map, looks up the corresponding entry in the output map. If it didn't already exist, it creates a new vector (via map::operator[]), otherwise, it returns the reference to the existing on. The vector in the second map is then appended to the vector already in the result.

The downside is you're searching the resulting map over and over again in the destination map, which seems to be a bit excessive. Since both maps are sorted, it should be able to do it in linear time, instead of N-log-N time.

Upvotes: 1

Related Questions