Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to change the comparator of a C++ std::set?

I have a set of data which in some occasion I need to sort them in one way and some occasion in another way. For example, suppose the data set is a set of strings,{"abc", "dfg",...}. Sometimes I need to sort them in alphabetic order and sometimes by comparing their length.

Initially I used std::set as a container of my data and implemented 2 comparators, hoping that I can change the comparator of the set on the fly, cause the data is huge and it's not a good idea to copy it from one set to another..I just want to sort it using different comparators from time to time. Is this possible or what's the right way to do it?

like image 674
blurrcat Avatar asked Oct 15 '11 12:10

blurrcat


2 Answers

You have to specify the comparator of std::set at construction time.

As a solution, I would maintain two 'index' sets instead, each referring to the actual collection. This would yield the greatest flexibility. To keep everything together, I suggest you wrap it up in a single class:

// to be compiled, debugged etc..., but ideal
// to grab  the idea
// caveats: maintain the index objects whenever the collection
// gets resized/reallocated etc...
// so not to be written yourself, use an existing library :)
template< typename T, typename comp1, typename comp2 >
struct MultiIndex {
    std::deque<T> collection;
    std::set<T*, comp1> index1;
    std::set<T*, comp2> index2;

    void insert( const T& t ){
       collection.push_back(t);
       index1.insert( &collection.back() );
       index2.insert( &collection.back() );
    }
};

Boost library has such a class: Multiindex.

like image 123
xtofl Avatar answered Dec 09 '22 23:12

xtofl


The set is internally always kept sorted (otherwise you wouldn't have the needed performance), so no, the comparator can't be changed. What I think the best solution here is to maintain two sets with same data, but with different comparators. I'd encapsulate the two sets in a class and have the functions like insertion work on both sets to ensure the data is the same on both sets.

If you only don't need to have the data sorted all the time, another way to accomplish what you want would be to simply use e.g. a vector and sort by whichever comparator you need when necessary.

like image 31
Antti Avatar answered Dec 09 '22 23:12

Antti