DoReMi
DoReMi

Reputation: 221

Can I later change sorting criteria of a map in C++?

Suppose I have a map, key as char and value as integer. Based on the property of black-red tree, every time I insert a new pair, the map will be sorted by char. After all insertion, I want to sort my map again by its value(i.e. the integer number). My question is, can I do this by my own compare function? Here is the code:

sort(mymap.begin(), mymap.end(), MyComp);

class MyComp
{
public:
    bool operator()(const pair<char, int>& x, const pair<char, int>& y) const
    {
        return x.second > y.second;
    }
};

My code can not compile, but I do not know why I can't do this. Can anyone help me?

And further more, if this is not a good way to solve the problem, is there any other way to do this?

I can think of a way that is to create another map and insert again by exchange the value and key, it works but waste much more space. Thanks!

Upvotes: 2

Views: 961

Answers (2)

Slava
Slava

Reputation: 44238

Sorting criteria for std::map is set only once upon creation and you cannot change it later neither you can rearrange existing data inside your map. So if you need to resort your data differently you can use different container like boost::multi_index that supports multiple cafeterias for sorting or copy data to another container and sort it.

Upvotes: 0

Dietmar K&#252;hl
Dietmar K&#252;hl

Reputation: 153820

You can't rearrange the elements of a std::map<K, V>: the value type of this map is actually std::pair<K const, V> and, thus, the elements are not Swappable as is required for std::sort().

You can, however, change the sorting criteria by customizing the predicate of the std::map<...> itself:

std::map<K, V, Compare> m;

Note, however, that the comparison function in Compare takes two K const& as argument, rather than a std::pair<K const, V>.

BTW, if you ever get an element from a std::map<K, V, ...>, the value type is not std::pair<K, V> but std::pair<K const, V>. However, often the latter type implicitly converts into the former, i.e., you can call

void f(std::pair<char, int> const&) { ... }

with a std::pair<char const, int>:

f(std::pair<char const, int>('a', 1));

This operation will, however, not just provide a reference to the original object but construct a new object. In the setup using char and int this isn't much of a problem but the conversion can be rather expensive, e.g., if one of the members is a std::string.

Upvotes: 3

Related Questions