tags:

views:

43

answers:

2

I get some strange behavior when inserting values into a map: I always insert at the end of the map, but sometimes the entries get out of order.

If I do a straight forward test, then I get no problems- the numbers are correctly ordered:

map<int,int> testMap;
for(int i = 0; i < 100; ++i)
{
    // everything is ordered correctly here
    testMap.insert(testMap.end(), pair<int,int>(i,i));
}

But when I parse a string and I try to insert the values in the same order as I read them, then things don't work out that well:

const string INPUT_TWO =
"=VAR STRING1 \"MYSTRING\"\n\
=VAR STRING2 \"EXAMPLE\"\n\
=VAR NUMBER1 12345\n\
=VAR NUMBER2 23456\n\
=VAR DUMMY 1111\n";

const string VAL_STRING = "VAR";

vector<pair<string, string>> parse_fields(const string & input)
{
    map<string, string> fieldsMap;
    vector<pair<string, string>> sequenceFields;
    vector<string> lines = split(input, '\n');
    for(size_t i = 0; i < lines.size(); ++i)
    {
        if(lines[i].find(VAL_STRING)!=string::npos)
        {
            vector<string> vals = split(lines[i], ' ');
            if(vals.size()==3)
            {
                fieldsMap.insert(fieldsMap.end(), pair<string,string>(vals[1], remove_quotes(vals[2])));
                sequenceFields.push_back(pair<string,string>(vals[1], remove_quotes(vals[2])));
            }
        }
    }

    // at the end the map looks like:
    // "DUMMY", "1111"
    // "NUMBER1", "12345"
    // "NUMBER2", "23456"
    // "STRING1", "MYSTRING"
    // "STRING2", "EXAMPLE"

    // the vector of pairs looks like:
    // "STRING1", "MYSTRING"
    // "STRING2", "EXAMPLE"
    // "NUMBER1", "12345"
    // "NUMBER2", "23456"
    // "DUMMY", "1111"

    return sequenceFields;
}

For your reference, I have pasted all the additional code in a pastie.

Does anybody know why this may be happening?

+3  A: 

A std::map is an ordered container, this is what allows it the look-up times it has. If you need both the mapping and listing, consider using Boost.MultiIndex.

GMan
GMan, I just thought about that and I was about to go and reverse the int map from 100 to 0 instead of 0 to 100... so now it all makes sense.
Lirik
+1  A: 

Maps are not inherently ordered. Conceptually, they represent key-value pairs. But C++ std::map maps are internally ordered. See http://www.cplusplus.com/reference/stl/map/ . So entries will effectively be sorted by key values.

If you need your own ordering, you should use a list of tuples. Or an unordered_map, if you have one (see http://en.wikipedia.org/wiki/Unordered_map_%28C%2B%2B%29 ; hash_map is probably available on your platform). Or sort the results as you retrieve them.

Borealid