Question

I have a little problem. I have a vector of pairs patternOccurences. The pairs are <string,int>, where string is the pattern(name) and int the index where it appears. My problem is that patternOccurences has multiple pairs with the same .first(same pattern) but different int values. For example: The vector has 10 entries. 5 of pattern "a" and 5 of pattern "b". all have different indices. Now i want to have a map (or something similar) so that i have a vector/list with each pattern(in my example "a" and "b") as a key and a vector of their indices as the value. The indices are in the different pairs in my vector of pairs and i want all indices for pattern "a" in a int vector as value for key "a".

I tried the following:

std::map<std::string,std::vector<int>> occ;
    for(int i = 0;i<patternOccurences.size();i++){
        if(occ.find(patternOccurences.at(i).first)==occ.end()){
            occ[patternOccurences.at(i).first]=std::vector<int>(patternOccurences.at(i).second);
        }
        else{
            occ[patternOccurences.at(i).first].push_back(patternOccurences.at(i).second);
        }
    }

patternOccurences is the vector of pairs and occ the desired map. First i check if there is already an entry for the string(pattern) and if not i create one with a vector as value. If there is already one I try to push_back the vector with the index. However it doesnt seem to be working right. For the first pattern i get a vector with 0 only as values and for the second there are only 3 indices which are right and the other ones are 0 as well.

I hope you can help me. Kazoooie

Was it helpful?

Solution

You are calling the constructor for the vector in the wrong way:

std::vector<int>(patternOccurences.at(i).second);

This creates a vector with N default constructed elements, not a vector with one element with value N. You need:

std::vector<int>(1, patternOccurences.at(i).second);

That should fix the problem, but your code doesn't have to be that complicated. The following would work just fine:

for(int i = 0;i<patternOccurences.size();i++){
    occ[patternOccurences.at(i).first].push_back(patternOccurences.at(i).second);
}

or with C++11, the even simpler:

for(auto& p:patternOccurences) {
    occ[p.first].push_back(p.second);
}

OTHER TIPS

What you are asking for already exists in STL and it's called std::multimap (and std::unordered_multimap).

Take a look here. Basically it's a map which allows more values to have the same key.

std::multimap<std::string, int> occ;

occ.insert(std::pair<std::string,int>("foo", 5));
occ.insert(std::pair<std::string,int>("foo", 10));

std::pair<std::multimap<std::string,int>::iterator, std::multimap<std::string,int>::iterator> group = occ.equal_range("foo");
std::multimap<std::string,int>::iterator it;

for (it = ret.first; it != ret.second; ++it) {
 ..
}

Change this statement

occ[patternOccurences.at(i).first]=std::vector<int>(patternOccurences.at(i).second);

to

occ[patternOccurences.at(i).first]=std::vector<int>(1, patternOccurences.at(i).second);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top