2010-09-02 11 views
5

Je cherche un conteneur, pour contenir des objets comme Employé (avec info: nom, salaire, téléphone ....) qui pourra être trié par nom (a..z) et d'autres fois trier par salaire par exemple. quelle est la meilleure façon de le faire? je pensais à la carte, mais je définir seulement 1 pour aller en apprécierait toute idée (pas trop avancée s'il vous plaît!)Conteneur STL avec plus d'une méthode de tri en C++

--- mise à jour ---

Je ne suis pas réellement besoin toujours 2 conteneurs STL, j'en aurais normalement 1 (disons les employés triés par nom de famille), et sur demande, cela ne me dérange pas de faire un nouveau conteneur STL, et de repasser tous les éléments, seulement cette fois pour être triés par salaire, donc je peux l'imprimer par cet ordre. Est-il possible de créer map1 avec tri par nom et map2 avec tri par salaire? Si oui, aimerait plus d'explications \ exemple pour définir ces 2 cartes. J'ai très peu de connaissances C++ (première affectation je suis arrivé)

Répondre

17

en utilisant cette version de std :: sort

template <class RandomAccessIterator, class Compare> 
void sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp); 

vous pouvez trier sur quel domaine (s) que vous souhaitez, apportez votre propre comparateur. Par exemple

struct CompareSalary 
{ 
    bool operator() (const Employee& a, const Employee& b) const 
    { 
    return a.salary < b.salary; 
    } 
} 

En outre, depuis std :: sort est compatible avec tous les conteneurs fournissant un iterator acess au hasard, std :: vecteur fera très bien.

+0

Je pense que vous voulez 'operator()'. –

+0

oups vous avez raison. fixé. – stijn

6

Fournir une fonctionnelle std::sort:

bool byName(Employee left, Employee right) { 
    return left.name < right.name; 
} 

std::vector<Employee> employees; 
std::sort(employees.begin(), employees.end(), byName); 
+0

@Ferruccio, en fait pas cette fois. Je passe un pointeur sur byName, sans appeler par Name. –

+0

Je venais juste d'attraper ça et j'ai supprimé mon commentaire. Je pensais à byName en tant que foncteur. :-) – Ferruccio

+0

@Philip: J'ajouterais 'const &' aux paramètres, pas besoin de déclencher le constructeur de copie pour une simple comparaison. –

0

Fondamentalement, vous voulez définir multicomparateur, chacun mis en œuvre pour répondre aux différents critères de tri. Le post de Philip Potter donne un exemple d'un critère de tri. Vous voudrez peut-être en définir quelques autres comme ça. La surcharge de l'opérateur less than vous permettra d'utiliser la méthode std :: sort avec les deux premiers paramètres seulement, mais vous serez limité à un seul critère de tri.

8

Si vous voulez que les deux critères de tri soient disponibles en même temps, vous pouvez aussi regarder dans Boost MultiIndex

Ps: Mais puisque vous avez mentionné que vous êtes nouveau C++ je ne vous recommandons d'utiliser Boost multiindice. Il est difficile de comprendre sa syntaxe

+1

(c'est boost, pas stl, mais) sauf pour ajouter/supprimer des entrées (sans compter le resort nécessaire alors), ceci est le moyen le plus efficace d'accéder aux données triées de différentes manières. Il a une déclaration "funky", mais il n'est pas trop avancé quand on suit les documents et travailler avec est assez simple. – stefaanv

0

Voulez-vous les trier à tout moment? Comme une carte std :: fait? (Donc, vous pouvez accéder à l'élément le plus bas avec *(coll.begin())?) Si oui, ce que je ferais est d'avoir deux std :: map, chacun rempli de shared_ptr<T>, chacun ayant son propre foncteur de tri, un pour chaque critère de tri. De cette façon, vous n'êtes pas limité à un seul opérateur "inférieur à" pour votre type de données, vous obtenez des insertions et des suppressions O (log n) (std :: map est juste un arbre binaire), et les cartes sont toujours triées .

Vous devrez synchroniser l'ajout et la suppression pour vous assurer qu'ils sont ajoutés et supprimés des deux cartes.

+1

Vous êtes en train de réinventer 10% de 'boost :: multi_index_container ' – MSalters