IdentifiantMot de passe
Loading...
Mot de passe oubli� ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les r�ponses en temps r�el, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Trier une map <string, double> par valeur en C++11 avec fonction lambda


Sujet :

C++

Vue hybride

Message pr�c�dent Message pr�c�dent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    14
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 14
    Par d�faut Trier une map <string, double> par valeur en C++11 avec fonction lambda
    Bonjour,

    J'ai une map dont les cl�s sont des strings et sont associ�es � des doubles. Je souhaiterais pouvoir trier cette map suivant les valeurs des doubles plut�t que sur les strings comme le fait par d�faut map. Y-a-t-il un moyen de faire cela avec un algorithme et une fonction lambda ?

    Cordialement

  2. #2
    Expert �minent

    Femme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    D�tails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (�le de France)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par d�faut
    map est pr�vue, concue et cod�e pour que les paires soient tri�es sur leur premier champ.
    En fait, tout se passe comme si map<K, V> �tait un set<pair<K, V>> dont le comparateur serait [...](p1, p2) {p1.first < p2.first}.

    Si tu veux que ta map soient tri� dans l'autre ordre, tu as deux solutions pistes possibles:
    faire un set dont l'ordre est sur le second champ de la paire
    faire deux maps (ou, variante, utiliser boost::bimap), mais cela suppose que les doubles sont uniques.

    Dans tous les cas, la simple map n'est pas ton ambition.

    Tu peux aussi faire une liste sp�ciale, qui contiendra (des pointeurs vers?) les cl�s, dans l'ordre o� tu souhaites les parcourir.
    (pour info, en Java, c'est ce que fait une LinkHashMap)

  3. #3
    Membre confirm� Avatar de Andarus
    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    Novembre 2008
    Messages
    137
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 37
    Localisation : France, Val de Marne (�le de France)

    Informations professionnelles :
    Activit� : D�veloppeur informatique
    Secteur : High Tech - �diteur de logiciels

    Informations forums :
    Inscription : Novembre 2008
    Messages : 137
    Par d�faut
    Cela ne semble pas �tre possible avec l'objet map.
    Mais tu peux toujours pass� par un vector.

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
     
    // sort algorithm example
    #include <iostream>     // std::cout
    #include <algorithm>    // std::sort
    #include <vector>       // std::vector
    #include <map>
    #include <string>
     
     
    //bool myFunction(std::pair<std::string, double> a, std::pair<std::string, double> b) {return a.second < b.second;}
    template <typename T1, typename T2>
    bool myFunction(std::pair<T1, T2> a, std::pair<T1, T2> b) {return a.second < b.second;}
     
     
    int main () 
    {
     
      std::string myStrings[] = {"lol", "lola", "loli"};
      double myDoubles[] = {3.0, 2.0, 1.0};
      std::map<std::string, double> myMap;
     
      for(int i=0; i<3; i++) // moche surement possible de faire mieux...
      {
          myMap[myStrings[i]] = myDoubles[i];
      }
     
     
     
      std::vector<std::pair<std::string, double> > mapCopy(myMap.begin(), myMap.end());
     
      std::sort (mapCopy.begin(), mapCopy.end(), myFunction<std::string, double>);
     
      for (std::map<std::string, double>::iterator it=myMap.begin(); it!=myMap.end(); ++it)
      {
        std::pair<std::string, double> a;
        a = *it;
        std::cout << a.first << " => " << a.second << '\n';
      }
      std::cout << '\n';
     
     
      for (std::vector<std::pair<std::string, double>>::iterator it=mapCopy.begin(); it!=mapCopy.end(); ++it)
      {
        std::cout << it->first << " => " << it->second << '\n';
      }
      std::cout << '\n';
     
      return 0;
    }
    Je ne suis pas s�r que cela r�ponde correctement � la question.

  4. #4
    R�dacteur/Mod�rateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 153
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 38
    Localisation : Canada

    Informations professionnelles :
    Activit� : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 153
    Billets dans le blog
    4
    Par d�faut
    T'es sur que t'as pas juste besoin de la parcourir � l'envers ?
    http://www.cplusplus.com/reference/map/map/rbegin/

    parce que l� on dirait que t'as choisi au hasard ton container, et as pris le plus mauvais possible dans ton cas
    pourquoi avoir une string en cl� si t'en fais rien ?
    Pensez � consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation r�seau ?
    Aucune aide via MP ne sera dispens�e. Merci d'utiliser les forums pr�vus � cet effet.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    14
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 14
    Par d�faut
    Je vois... Mais n'y-a-t-il pas une formule de la mort du genre sort(My_map.begin(),My_map.end(),Une_Fonction_Lambda_de_la_Mort) pour trier My_map par valeurs ?

  6. #6
    R�dacteur/Mod�rateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 153
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 38
    Localisation : Canada

    Informations professionnelles :
    Activit� : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 153
    Billets dans le blog
    4
    Par d�faut
    Comme on te l'a d�j� dit, une map �a se trie pas par valeur donc.. � nouveau... non!
    Pensez � consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation r�seau ?
    Aucune aide via MP ne sera dispens�e. Merci d'utiliser les forums pr�vus � cet effet.

  7. #7
    Membre �m�rite
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    307
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2009
    Messages : 307
    Par d�faut
    Passe par un vector et tri apr�s, ta structure de map est mal adapt�e tu devrais surement ne pas l'utiliser ou alors que temporairement.

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
     
    std::vector< std::pair< std::string, double >> toto(myMap.begin(), myMap.end());
    std::sort(toto.begin(), toto.end(), [](auto x, auto y) { return x.second() < y.second(); });
    modulo la syntaxe precise

  8. #8
    Membre Expert
    Homme Profil pro
    �tudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activit� : �tudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Par d�faut
    Hello,
    Citation Envoy� par durn1818 Voir le message
    J'ai une map dont les cl�s sont des strings et sont associ�es � des doubles. Je souhaiterais pouvoir trier cette map suivant les valeurs des doubles plut�t que sur les strings comme le fait par d�faut map. Y-a-t-il un moyen de faire cela avec un algorithme et une fonction lambda ?
    Dans ce cas pourquoi ne pas avoir une std::map<double, std::string> ?(Ou une std::multimap si tes doubles ne sont pas uniques).

    Si tu as besoin du tri par std::string et par double tu peux maintenir 2 std::map.
    Boost propose peut �tre ce genre de conteneur tout fait, sinon encapsul�s dans une classe perso du type :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    template <class Key, class Value>
    struct KVMap {
        typedef Key key_t;
        typedef Value value_t;
     
        typedef std::map<key_t, value_t> kv_map_t;
        typedef std::map<value_t, key_t> vk_map_t;
     
        typedef kv_map_t::const_iterator kv_c_iter;
        typedef kv_map_t::iterator kv_iter;
     
        typedef vk_map_t::const_iterator vk_c_iter;
        typedef vk_map_t::iterator vk_iter;
     
        kv_map_t m_byKeys;
        vk_map_t m_byValues;
     
        kv_c_iter byKeysBegin() const { return m_byKeys.begin(); }
        kv_iter byKeysBegin() { return m_byKeys.begin(); }
        kv_c_iter byKeysEnd() const { return m_byKeys.end(); }
        kv_iter byKeysEnd() { return m_byKeys.end(); }
     
        vk_c_iter byValuesBegin() const { return m_byValues.begin(); }
        vk_iter byValuesBegin() { return m_byValues.begin(); }
        vk_c_iter byValuesEnd() const { return m_byValues.end(); }
        vk_iter byValuesEnd() { return m_byValues.end(); }
     
        kv_c_iter find(key_t const& key) const { return m_byKeys.find(key); }
        vk_c_iter find(value_t const& value) const { return m_byValues.find(value); }
     
        // ...
    }

  9. #9
    Expert �minent

    Femme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    D�tails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (�le de France)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par d�faut
    la version boost est boost::bimap

  10. #10
    Expert �minent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activit� : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par d�faut
    Salut,

    Avant de r�pondre � la question du "comment", j'aimerais tr�s fort poser la question du "pourquoi":
    • Pourquoi ta map utilise-t-elle une std::string comme cl�, alors que la comparaison des chaines de caract�res est particuli�rement lente
    • Pourquoi ta map utilise-t-elle un double comme valeur
    • Pourquoi voudrais tu disposer de ces doubles sous une forme tri�e (quel que soit le crit�re de tri de ceux-ci)
    • (bon, ce n'est plus un "pourquoi" ) tes doubles sont-ils suffisamment diff�rents pour �tre effectivement consid�r�s comme uniques
    • En enfin (bon, ce n'est plus un pourquoi non plus ) Est ce que ce tri doit -- d'une mani�re ou d'une autre -- �tre pr�serv�, voire, pr�server les cl�s qui y sont associ�es

    Ces questions peuvent te paraitre �tranges, mais elles nous permettront (du moins, je l'esp�re) de nous faire une id�e bien plus pr�cise de tes besoins et du coup de te diriger plus efficacement vers la solution qui te conviendra
    A m�diter: La solution la plus simple est toujours la moins compliqu�e
    Ce qui se con�oit bien s'�nonce clairement, et les mots pour le dire vous viennent ais�ment. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 f�vrier 2014
    mon tout nouveau blog

  11. #11
    Membre averti
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    14
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 14
    Par d�faut Merci
    Bonjour,

    Et merci beaucoup pour toutes ces r�ponses.

    Sur le pourquoi, je n'y peux rien, c'est le probl�me qui m'a �t� donn� comme �a. J'ai finalement opt� pour la multimap <double, string> et �a marche simplement. Merci � tous. Je suis tr�s fier que des experts C++ se soient int�ress�s � mon message ! Tant pis s'il n'y a pas une formule en une ligne avec des lambda fonctions qui d�finiraient le comparateur.

    Cordialement

Discussions similaires

  1. Trier une Map sur les valeurs de fa�on d�croissante
    Par ddams dans le forum Collection et Stream
    R�ponses: 13
    Dernier message: 27/12/2011, 18h33
  2. Comment trier une map de type Map<String, Map<Integer, Integer>>
    Par khalidlyon dans le forum Collection et Stream
    R�ponses: 5
    Dernier message: 12/01/2010, 14h31
  3. Trier une Map<Long, String> par rapport aux donn�es
    Par zuzuu dans le forum Collection et Stream
    R�ponses: 9
    Dernier message: 26/03/2009, 10h03
  4. Trier une map sur valeur int
    Par totoche dans le forum Collection et Stream
    R�ponses: 9
    Dernier message: 09/05/2008, 11h54
  5. Trier une map
    Par lili2704 dans le forum Collection et Stream
    R�ponses: 2
    Dernier message: 10/04/2008, 13h23

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo