2017-09-23 2 views
0

Je veux faire unique et commander en set<Foo, FooComp>.C++ ensemble unique et l'ordre

Dans le code ci-dessous, je veux un à unique et ordonner par b et c. Donc, pas même foo.a et commandez par foo.b et foo.c.

Comment est-ce que je peux faire ceci?

struct Foo { 
    int a, b, c; 
    Foo(int a, int b, int c) : a(a), b(b), c(c) {} 
} 

struct FooComp { 
    bool operator() (const Foo& f, const Foo& s) const { 
     if (f.pattern == s.pattern) { 
      return false; 
     } 
     if (f.start == s.start) { 
      return f.length < s.length; 
     } 
     return f.start < s.start; 
    } 
} 

ou est-ce que j'utilise d'autres structures STL ou de données?

+0

et je pense que sur l'utilisation de la carte, comme la clé 'A' et' (b, c) 'en tant que valeur. mais, carte n'a pas conçu pour ce cas (je pensais). – Maybe

Répondre

0

Cela n'est pas possible avec le jeu de bibliothèques standard.

L'opérateur de comparaison est étroitement couplé à la commande.

Bien qu'un peu pire solution en termes de performance, vous pourriez avoir un ensemble qui contient tous vos objets, triées par « a » seulement en utilisant:

struct Foo { 
    int a, b, c; 
    Foo(int a, int b, int c) : a(a), b(b), c(c) {} 
    bool operator<(const Foo& rhs) const { 
     return a < rhs.a; 
    } 
    friend ostream& operator<<(ostream&, const Foo&); 
}; 

Et puis, chaque fois que vous voulez faire le tri à l'aide votre algorithme unique, il suffit de copier dans un vecteur et le tri en fonction de vos besoins:

vector<Foo> v; 
std::copy(s.begin(), s.end(), std::back_inserter(v)); 
std::sort(v.begin(), v.end(), [](const Foo& lhs, const Foo& rhs){ return (lhs.b == rhs.b) ? lhs.c > rhs.c : lhs.b > rhs.b; }); 

Edité

Cela implémente la logique que vous avez utilisée dans votre exemple Pastebin. Échantillon entier here

+0

Cela ne fonctionne pas comme je le pense. Dans ce code (https://pastebin.com/dCBpcQB2), je pense 1, 2, 3 2, 3, 1 3, 5, 2 mais résultat est 1, 2, 3 2, 3, 1 3, 5, 2 1, 5, 7 – Maybe

+0

@Maybe, j'ai mis à jour ma réponse –

+0

et je connais cette réponse, mais c'est la meilleure réponse? Je ne suis pas sûr ... – Maybe

0

Il existe une bibliothèque prête à l'emploi pour ce type de chose appelée boost.multi_index.

Permet la déclaration d'un conteneur qui satisfait plusieurs index et leurs contraintes.

C'est un peu archaïque et pourrait faire avec un peu d'amour, mais il fait le travail.

Vous pouvez commencer avec quelque chose comme ceci:

struct Foo { 
    int a, b, c; 
    Foo(int a, int b, int c) : a(a), b(b), c(c) {} 
}; 

#include <tuple> 
#include <type_traits> 
#include <utility> 
#include <boost/multi_index_container.hpp> 
#include <boost/multi_index/member.hpp> 
#include <boost/multi_index/ordered_index.hpp> 


struct get_a 
{ 
    using result_type = int const&; 
    result_type operator()(Foo const& l) const { 
     return l.a; 
    } 
}; 

struct get_bc 
{ 
    using result_type = std::tuple<int const&, int const&>; 

    result_type operator()(Foo const& l) const { 
     return std::tie(l.b, l.c); 
    } 
}; 

namespace foo { 
    using namespace boost; 
    using namespace boost::multi_index; 

    struct by_a {}; 
    struct by_bc {}; 

    using FooContainer = 
multi_index_container 
< 
    Foo, 
    indexed_by 
    < 
     ordered_unique<tag<by_a>, get_a>, 
     ordered_non_unique<tag<by_bc>, get_bc> 
    > 
>; 
} 

int main() 
{ 
    foo::FooContainer foos; 

    foos.insert(Foo{ 1, 2,3 }); 
    foos.insert(Foo{ 2, 2,4 }); 

} 
+0

wow, merci beaucoup, mais booster la bibliothèque n'est pas autorisée dans mon environnement. – Maybe