2010-12-10 10 views
4

J'ai vecteur des structures:STL genre question

vector<Custom> myvec; 

personnalisé est une structure:

struct Custom 
{ 
    double key[3]; 
}; 

Comment trier myvec par touche [0]. touche [1] ou touche [2] utilisant l'algorithme de tri STL?

Répondre

12

Ecrire un comparateur personnalisé:

template <int i> struct CustomComp 
{ 
    bool operator()(const Custom& lhs, const Custom& rhs) const 
    { 
    return lhs.key[i]<rhs.key[i]; 
    } 
}; 

et puis trier par exemple en utilisant std::sort(myvec.begin(),myvec.end(),CustomComp<0>()); (ce genre par la première entrée clé)

ou avec un compilateur plus récent (avec C++ 0x support lambda):

std::sort(myvec.begin(), myvec.end(), 
    [](const Custom& lhs, const Custom& rhs) {return lhs.key[0] < rhs.key[0];} 
); 
+0

+1. La version du template se sent ici beaucoup plus adaptée. –

+2

"Le faire fonctionner, le profil, le rendre rapide" - aucune raison d'optimiser quand ce n'est pas nécessaire. L'utilisation d'un modèle vous empêche de sélectionner un index lors de l'exécution, c'est pourquoi je ne l'ai pas fait. – etarion

+0

Je n'ai pas choisi la version du modèle sur la version non-template uniquement pour des raisons d'optimisation ou de rapidité. Je le trouve aussi plus propre puisque vous n'avez pas besoin de définir des variables membres et un constructeur. Ne pas dire que l'argument d'utiliser une variable membre est vide, mais il peut aussi être utilisé contre la décision même: pourquoi sur-concevoir et implémenter certaines fonctionnalités dont vous n'avez pas besoin? – ltjax

10

En utilisant un comparateur personnalisé.

struct CustomLess { 
    size_t idx; 
    CustomLess(size_t i) : idx(i) {} 
    bool operator()(Custom const& a, Custom const& b) const { 
     return a.key[idx] < b.key[idx]; 
    } 
}; 

puis

std::sort(myvec.begin(), myvec.end(), CustomLess(1)); // for 1 

Note: Je n'ai pas utilisé un modèle parce que, tout en utilisant un modèle permet au compilateur d'optimiser pour cet indice spécifique, il vous empêche de sélectionner l'index à l'exécution, par exemple basé sur userinput, donc il est moins flexible/ne peut pas faire autant que la version non prévue. Et comme nous le savons tous, l'optimisation prématurée est le mal :)

+0

+1, la façon de le faire plus simple si . Le modèle struct CustomLess' échange de la flexibilité pour plus d'efficacité. Mais vous ne le choisirez qu'après le profilage – MSalters

+0

@etarion: OK, merci! – qutron

+0

Il vous manque un '()' pour le 'operator' – Naveen

0
bool CompareCustoms(const Custom& lhs, const Custom& rhs) 
{ 
    // Compare criteria here 
    return (lhs.key[0] < rhs.key[0]); 
} 
sort(myvec.begin(), myvec.end(), CompareCustoms); 
+0

Oups, je vois les réponses beaucoup plus propres ci-dessus ici. J'ai appris quelque chose aussi :). – hillel

+1

@hillel: En général, les objets fonction sont meilleurs pour cela que les fonctions. Ils s'informent mieux que les fonctions appelées par adresse et ils permettent de porter l'état avec la fonction (au lieu de devoir le stocker globalement). – sbi

+0

@sbi: Je suis souvent paresseux avec la création de bons foncteurs et je n'ai jamais pris en compte. Merci pour votre commentaire. – hillel

2

Je ne sais pas pourquoi tant de des réponses postées se concentrent sur les foncteurs. Il n'y a pas besoin d'un foncteur avec l'exigence indiquée de l'OP. Voici les 2 solutions non-foncteur:

1: opérateur de surcharge < dans la classe personnalisée

bool Custom::operator< (const Custom& rhs) 
{ 
    return key[0] < rhs.key[0]; 
} 

// can call sort(myvec.begin(), myvec.end()); 

2: Créer une fonction de comparaison personnalisée

template<int i> bool CustomLess(const Custom& lhs, const Custom& rhs) 
{ 
    return lhs.key[i] < rhs.key[i]; 
} 

// can call sort(myvec.begin(), myvec.end(), CustomLess<0>);