Right now I have a map and I need to sort it by value(int), and then by key(string) if there is a tie. I know I would need to write a customized comparison function for this, however so far I haven't been able to make it work. (I need to store my stuffs in a map since the strings are words and ints are the frequencies and I will need to 'find' the pairs by searching the keys later)
3 Answers
The std::map can only be sorted by key (string in your case).
If you need to sort it by value as well, you'd need to create a std::multimap with the int as key and the string as value, and populate it by iterating over the map.
Alternatively, you could also create a vector<pair<int,string>> that you populate by iteration over the map and just use std::sort().
Comments
You can use a std::multiset<std::pair<int, std::string>>
2 Comments
Phil1970
Why that instead of simpler
std::multimap<int, string>>?aeroyorch
std::multimap orders by key not by value. Insertion of elements with same key are not ordered by value (en.cppreference.com/w/cpp/container/multimap/insert): "If the container has elements with equivalent key, inserts at the upper bound of that range." (since C++11). Hence using a std::multiset or std::set of pairs provides a way of ordering both.With the information given, it's a bit of a guessing game, but unless you are shuffling massive amounts of data, this may do.
using entry = std::pair<std::string, int>;
using CompareFunc = bool(*)(const entry&, const entry&);
using sortset = std::set<entry, CompareFunc>;
sortset bv(themap.begin(), themap.end(), [](auto& a, auto&b){ a.second!=b.second?a.second<b.second:a.first<b.first; });
for(const auto& d : bv) {
//
}
2 Comments
Matthieu Brucher
Why not simply a set of (int, std::string), and then you can remove the useless operator?
Ted Lyngmo
I agree, that sounds cleaner, but then I'd need to transform the map, wouldn't I?
std::map<K, V>is always sorted by key. So, store it in a different container, maybe even astd::map<V, K>orstd::multimap<V, K>.std::set<std::pair<std::string, int>>and provide the set with your comparison function would work? That set should be constructable via your maps iterators.