Qual è il modo più semplice di definire confronto lessicografico per gli elementi di una classe?
-
21-09-2019 - |
Domanda
Se ho una classe che voglio essere in grado di ordinare (vale a dire sostenere una minore di concetto), e ha diversi elementi di dati tali che ho bisogno di fare ordinamento lessicografico quindi ho bisogno di qualcosa di simile:
struct MyData {
string surname;
string forename;
bool operator<(const MyData& other) const {
return surname < other.surname || (surname==other.surname && forename < other.forename); }
};
Questo diventa piuttosto ingestibile per qualsiasi cosa con più di 2 membri di dati. Ci sono dei modi più semplici di realizzarlo? I membri di dati possono essere qualsiasi classe Comparable.
Soluzione 2
Con l'avvento di C ++ 11 c'è un modo nuovo e conciso per raggiungere questo obiettivo utilizzando std :: cravatta :
bool operator<(const MyData& other) const {
return std::tie(surname, forename) < std::tie(other.surname, other.forename);
}
Altri suggerimenti
tuple
è una buona idea, ma se si vuole continuare ad avere i nomi per le variabili membro, potrebbe essere sufficiente per ristrutturare la vostra funzione di confronto in questo modo:
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
}
};
A seconda del vostro gusto, si potrebbe anche voler una macro come #define COMPARE(field) if (field != other.field) return field < other.field;
per ridurre la duplicazione. Poi la funzione sarebbe solo diventare un elenco di COMPARE
-invocazioni.
È possibile memorizzare i dati in un boost::tuple
, che fornisce il confronto lessicografico, e di fornire funzioni di accesso con nome, lungo le linee di:
#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;
};
Credo che questo è disponibile anche come std::tr1::tuple
, e verrà std::tuple
nella prossima serie.
Il mantenimento della lista delle funzioni di accesso è probabilmente più gestibile rispetto mantenendo il codice di confronto.
Se tutti i membri hanno lo stesso tipo si potrebbe metterli in std::vector
. Per impostazione predefinita std::lexicographical_compare
sarà utilizzato per confrontare i vettori.
È possibile utilizzare un boost::tuple
o std::pair
che è incorporato in confronto lexigraphical. Naturalmente lo svantaggio è che non è possibile associare un metodo per le tuple.