Каков самый простой способ определить лексикографическое сравнение для элементов класса?

Если у меня есть класс, который я хочу смочь отсортировать (т.е. поддерживать меньше понятие), и оно имеет несколько элементов данных, таким образом, что я должен сделать лексикографическое упорядочивание затем, мне нужно что-то вроде этого:

struct MyData {
  string surname;
  string forename;

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

Это становится довольно неуправляемым для чего-либо больше чем с 2 элементами данных. Есть ли какие-либо более простые способы достигнуть его? Элементы данных могут быть любым Сопоставимым классом.

12
задан the_mandrill 23 March 2010 в 14:28
поделиться

4 ответа

Вы можете хранить данные в boost :: tuple , который обеспечивает лексикографическое сравнение и предоставляет именованные функции доступа в соответствии со строками of:

#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>

struct Data {
    string &surname()  {return stuff.get<0>();}
    string &forename() {return stuff.get<1>();}

    // it would be polite to add const overloads too.

    bool operator<(const Data &other) const {return stuff < other.stuff;}

private:
    boost::tuple<string, string> stuff;
};

Я считаю, что это также доступно как std :: tr1 :: tuple , и будет std :: tuple в следующем стандарте.

Поддерживать список средств доступа, вероятно, проще, чем поддерживать код сравнения.

6
ответ дан 2 December 2019 в 05:15
поделиться

tuple - хорошая идея, но если вы хотите сохранить имена для ваших переменных-членов, возможно, будет достаточно перестроить вашу функцию сравнения следующим образом:

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
    }
};

В зависимости от вашего вкуса, вы можете даже захотеть макрос типа #define COMPARE(field) if (field != other.field) return field < other.field; чтобы уменьшить дублирование. Тогда функция просто превратится в список COMPARE-вызовов.

10
ответ дан 2 December 2019 в 05:15
поделиться

Если все члены имеют один и тот же тип, вы можете поместить их в std :: vector . По умолчанию для сравнения векторов будет использоваться std :: lexicographic_compare .

3
ответ дан 2 December 2019 в 05:15
поделиться

Вы можете использовать boost :: tuple или std :: pair со встроенным лексиграфическим сравнением. . Конечно, недостатком является то, что вы не можете связать метод с кортежами.

2
ответ дан 2 December 2019 в 05:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: