Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the simplest way of defining lexicographic comparison for elements of a class?

If I have a class that I want to be able to sort (ie support a less-than concept), and it has several data items such that I need to do lexicographic ordering then I need something like this:

struct MyData {
  string surname;
  string forename;

  bool operator<(const MyData& other) const {
    return surname < other.surname || (surname==other.surname && forename < other.forename); }
};

This becomes pretty unmanageable for anything with more than 2 data members. Are there any simpler ways of achieving it? The data members may be any Comparable class.

like image 907
the_mandrill Avatar asked Mar 23 '10 14:03

the_mandrill


People also ask

What does lexicographical comparison mean explain with examples?

Definition: Lexicographic order and comparison. Lexicographic ordering means dictionary like ordering on types that have several elements in some defined sequence. If the first element of a sequence A is less than the first element of a sequence B then A is lexicographically less than B .

What is lexicographical method?

With the lexicographic method, preferences are imposed by ordering the objective functions according to their importance or significance, rather than by assigning weights. After we arrange the objective functions by importance, the most important objective is solved first as a single-objective problem.

What is lexicographical order example?

Lexicographical order is nothing but the dictionary order or preferably the order in which words appear in the dictonary. For example, let's take three strings, "short", "shorthand" and "small". In the dictionary, "short" comes before "shorthand" and "shorthand" comes before "small". This is lexicographical order.


2 Answers

With the advent of C++11 there's a new and concise way to achieve this using std::tie:

bool operator<(const MyData& other) const {
  return std::tie(surname, forename) < std::tie(other.surname, other.forename);
}
like image 100
the_mandrill Avatar answered Sep 29 '22 17:09

the_mandrill


tuple is a good idea, but if you want to keep having names for your member variables, it might be good enough to restructure your comparison function like this:

struct MyData {
    string surname;
    string forename;
    string var;
    // ...

    bool operator<(const MyData& other) const {
        if (surname != other.surname) return surname < other.surname;
        if (forename != other.forename) return forename < other.forename;
        if (var != other.var) return var < other.var;

        // ...

        return false; //< They are equal
    }
};

Depending on your taste, you might even want a macro like #define COMPARE(field) if (field != other.field) return field < other.field; to reduce duplication. Then the function would just become a list of COMPARE-invocations.

like image 38
Magnus Hoff Avatar answered Sep 29 '22 19:09

Magnus Hoff