1

Sorry if the question title terminology is wrong, but here is what I want to do.I need to sort a vector of objects, but contrary to a typical comparison "less than" approach I need to re-position the objects based on some string ID property so that each same type members are positioned in consecutive order like this:

[id_town,id_country,id_planet,id_planet,id_town,id_country]

becomes this:

[id_town,id_town,id_country,id_country,id_planet,id_planet]

id_ property is string.

Community
  • 1
  • 1
Michael IV
  • 11,016
  • 12
  • 92
  • 223

1 Answers1

9

std::sort has a third parameter which can be used to pass a boolean predicate that acts as custom comparator. Write your own comparator acording to your specifications and use it.

For example:

struct foo
{
    std::string id;

    foo(const std::string& _id) : id( _id ) {}
};

//Functor to compare foo instances:
struct foo_comparator
{
    operator bool(const foo& lhs , const foo& rhs) const
    {
        return lhs.id < rhs.id;
    }
};

int main()
{
    std::vector<foo> v;

    std::sort( std::begin(v) , std::end(v) , foo_comparator );
}

Also, in C++11 you could use a lambda:

std::sort( std::begin(v) , std::end(v) , [](const foo& lhs , const foo& rhs) { return lhs.id < rhs.id; } );

Finally, you can also overload the comparison operators (operator> and operator<) and use comparators provided by the standard library like std::greater:

struct foo
{
    std::string id;

    foo(const std::string& _id) : id( _id ) {}

    friend bool operator<(const foo& lhs , const foo& rhs)
    {
        return lhs.id < rhs.id;
    }

    friend bool operator>(const foo& lhs , const foo& rhs)
    {
        return rhs < lhs;
    }

    friend bool operator>=(const foo& lhs , const foo& rhs)
    {
        return !(lhs < rhs);
    }

    friend bool operator<=(const foo& lhs , const foo& rhs)
    {
        return !(lhs > rhs);
    }
};


int main()
{
    std::vector<foo> v;

    std::sort( std::begin(v) , std::end(v) , std::greater );
}
Manu343726
  • 13,969
  • 4
  • 40
  • 75
  • @MichaelIV Note that the utilities library provides the implementation of all relational operators based on `operator==` and `operator<`: http://en.cppreference.com/w/cpp/utility/rel_ops/operator_cmp, so if you include that libray you only have to write that two last operators. – Manu343726 Sep 06 '13 at 14:42
  • Great!Thanks!Read about functors once but never realized how useful these can be. – Michael IV Sep 06 '13 at 14:42
  • @MichaelIV you do not have to include (`using` sentence) the `std::rel_ops` namespace, because the overloads will be finded through [*Argumment Dependent Lookup* (ADL)](http://stackoverflow.com/a/3623643/1609356) – Manu343726 Sep 06 '13 at 14:48
  • Shouldn't you pass an object instead of class? That is,`sort(begin(v), end(v), foo_comparator())` – Siyuan Ren Nov 15 '13 at 17:08