STL Map sorting
c++, dictionary, sorting, stl
Solution
A `std::map` is sorted. There is no way to construct a `map` that isn't sorted.
The problem isn't the fact that the `map` is sorted. The problem is how your keys are designed.
You've said that your key is a date, but what it really is is a `string`. How can the `map` know that the data in the `string` is actually a date, and that it should sort somehow by the year first, then the month, then the day? It can't. You have to tell it to do this.
Change your keys to be strings in this format:
`YYYYMMDD`
where `Y`, `M` and `D` are all numeric. Don't try to use `NOV` for november -- use `11` instead.
You could also use `unsigned long`s for the key instead of `string`s. This would make comparison quicker, but computing the values is a bit trickier.
If you must stick to the original format for they keys, then you have a bit of work to do. The map is sorted according to the map's comparator, which is specified as one of it's template parameters:
[C++03 Example]
struct CompareDates
:
public std::binary_function <bool, std::string, std::string>
{
bool operator() (const std::string& lhs, const std::string& rhs)
{
// return true if lhs < rhs
// return false otherwise
// step 1: compare years. if lhs.year < rhs.year, return true. else, continue
// step 2: compare months. if lhs.month < rhs.month, return true. else, continue.
// note: don't just compare the strings, else "AUG" < "JAN" etc
// step 3: compare days. if lhs.day < rhs.day, return true. else, return false.
}
};
Since this appears to be homework, I'll let you fill in the missing bits above. :)
Using this comparator to compare keys, you can instantiate a map that does the correct sorting automatically:
std::map <Key, Value, CompareDates> myMap;
Problem
UPDATED: I have followed John's guidance and modified his code which solved my problem via creating a comparator function and and insert it to the Compare parameter in STL map. Since my string date are strictly in the shown format, using substr will be fine. My output and codes are below for your reference. ``` Date Total Sales 01JAN1900 $4 20JAN1902 $40 18NOV1912 $2500 19NOV1912 $2500 19OCT1923 $25 01JAN1991 $22 15NOV1991 $300 Grand Total: $5391 struct CompareDates : public std::binary_function <bool, std::string, std::string> { bool operator() (const std::string& lhs, const std::string& rhs) { if(lhs.substr(5,4) < rhs.substr(5,4)) { return true; } else if (lhs.substr(5,4) == rhs.substr(5,4) && lhs.substr(2,3) < rhs.substr(2,3)) { return true; } else if (lhs.substr(5,4) == rhs.substr(5,4) && lhs.substr(2,3) == rhs.substr(2,3) && lhs.substr(0,2) < rhs.substr(0,2)) { return true; } else { return false; } } }; map<string, double,CompareDates> dailyDatePrices; ``` Initial Problem: I am required to sort raw data into a daily report format. As such I have used STL `map` to store the date as the key and the item price as the value. From what I read, STL map is automatically sorted. However I do not want it to be sorted by map as it will generate the undesired current report output stated below. I will want to sort based on the string date(earliest to latest) and will want it to be that exact format. I have used vector and function comparator to sort the date already before using map. Is there any way to go about doing it? Thanks! ``` Raw Data STRAW:10:15NOV1991 TOY:10:15NOV1991 BARLEY:5:01OCT1992 Undesired Current Report Output 01OCT1992 5 15NOV1991 20 Expected Report Output 15NOV1991 20 01OCT1992 5 ```