Qual è il modo più semplice di definire confronto lessicografico per gli elementi di una classe?

StackOverflow https://stackoverflow.com/questions/2500664

  •  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.

È stato utile?

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top