0

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)

9
  • A std::map<K, V> is always sorted by key. So, store it in a different container, maybe even a std::map<V, K> or std::multimap<V, K>. Commented Dec 2, 2018 at 0:36
  • That's not how maps work. Unless you want to get into the new transparent comparison stuff, but you're still not going to get performance out of that. Have you considered maintaining an index container alongside the data container? Why do you think you need to sort by value then key? Is that purely for iteration purposes? Again, if your iteration and lookup have different requirements then that's a flag that you need a second, view-like container IMO. One thing that might be useful for you here is a bimap... Commented Dec 2, 2018 at 0:37
  • @Deduplicator That just moves the goalposts because now you broke lookup-by-K. Commented Dec 2, 2018 at 0:39
  • 1
    Perhaps populating a 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. Commented Dec 2, 2018 at 0:44
  • 3
    Possible duplicate of Sorting std::map using value Commented Dec 2, 2018 at 1:03

3 Answers 3

1

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().

Sign up to request clarification or add additional context in comments.

Comments

1

You can use a std::multiset<std::pair<int, std::string>>

2 Comments

Why that instead of simpler std::multimap<int, string>>?
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.
0

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

Why not simply a set of (int, std::string), and then you can remove the useless operator?
I agree, that sounds cleaner, but then I'd need to transform the map, wouldn't I?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.