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 :

Ordre des éléments d'une map<int, string>


Sujet :

C++

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    61
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 61
    Points : 43
    Points
    43
    Par défaut Ordre des éléments d'une map<int, string>
    Bonjour,

    Je souhaite associer à chaque clef d'une map l'ordre dans lequel il apparait dans l'ordre de la suite des clefs de la map.

    Par exemple pour la première clef j'associe la valeur 1, pour la deuxième clef j'associe le valeur 2 etc...

    Sachant que les clefs d'une map sont classées par ordre croissant, puis-je accéder directement à l'ordre de chaque clef ou dois je faire l'association?

    Merci d'avance.

  2. #2
    Membre émérite

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Points : 2 252
    Points
    2 252
    Par défaut
    J'ai rien compris

    Je souhaite associer à chaque clef d'une map l'ordre dans lequel il apparait dans l'ordre de la suite des clefs de la map.
    Désolé, pour moi c'est du charabia. "l'ordre dans lequel il apparait dans l'ordre de la suite des clefs de la map" !?? Déjà c'est qui ou quoi "il" dans cette phrase ?

    Par exemple pour la première clef j'associe la valeur 1, pour la deuxième clef j'associe le valeur 2 etc...
    Dans une std::map<int, std::string> la clé c'est l'int, la valeur c'est la string. Tu ne peux pas affecter 1 ou 2 à une string...

    Sachant que les clefs d'une map sont classées par ordre croissant, puis-je accéder directement à l'ordre de chaque clef ou dois je faire l'association?
    Qu'est-ce que ça veut dire "accéder directement à l'ordre de chaque clef" ?

    Si tu veux accéder à la n-ième paire [clé, valeur] de la map alors il faut passer par les itérateurs :

    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
    #include <string>
    #include <map>
    #include <iostream>
     
    int main()
    {
       std::map<int, std::string> m;
       m[1] = "toto";
       m[2] = "titi";
       m[3] = "tutu";
     
       int n = 3;
     
       // std::next dispo uniquement sur les compilateurs récents
       std::map<int, std::string>::iterator it = std::next(m.begin(), n -1);
       std::cout <<it->first << " : " << it->second << "\n";
     
       // si std::next n'est pas présent il reste toujours std::advance 
       std::map<int, std::string>::iterator it2 = m.begin();
       std::advance(it2, n -1);
       std::cout <<it2->first << " : " << it2->second << "\n";
     
       // les deux méthodes précédentes sont équivalentes à :
       std::map<int, std::string>::iterator it3 = m.begin();
       for(int i = 0 ; i < n - 1; i++)
       {
          it3++;
       }
       std::cout <<it3->first << " : " << it3->second << "\n";
    }
    (Ce qui revient en fait à faire un parcours en profondeur de l'arbre binaire sous-jacent à std::map)

  3. #3
    Invité
    Invité(e)
    Par défaut
    Tu as aussi la fonction distance(), qui renvoie le nombre d'éléments entre deux itérateurs sur un conteneur. Donc quelque chose comme

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    distance(mamap.begin(),monelement);
    (monelement est un itérateur sur l'élément que tu veux...)

    renverra 0 pour le premier élément, 1 pour le second, etc... En terme de code, c'est exactement comme ce qu'écrit Arzar, mais cela marchera avec n'importe quel conteneur (quel que soit le type de ses éléments).

    Ceci appelle deux remarques :

    1- l'appel à distance() parcourt la map, ce n'est donc pas une fonction très rapide
    2- si tu ajoutes ou enleve des éléments, il faut appeler distance(), plutôt que stocker les "positions" dans un champ supplémentaire de la map. Car leurs valeurs seront invalidées à chaque ajout/suppression d'élément.

    Francois

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    61
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 61
    Points : 43
    Points
    43
    Par défaut
    Merci pour les réponses et désolé de la qualité de l'explication.

    Merci d'avoir essayé de comprendre, et du coup ce que vous avez pensez, c'était bien ça la question. Je voulais stocker les "positions" (rang) des clefs : c'est à dire faire une map qui associe à chaque clef son rang.

    Le but du jeu c'est de considérer toutes mes clefs 2 à 2 et chercher à savoir si (en terme de rang) elles se succèdent ou pas?
    Dit autrement, voir les quelles clefs sont adjacents.

    Sachant que les valeurs de mes clefs n'ont pas de structure uniforme.
    La seule manière de savoir si elles se suivent est de chercher la valeur absolue |rang clef1 - rang clef2|. Si cette valeur absolue est égale à 1 les deux clef se succèdent sinon elle ne se succèdent pas.

    Bon en tout cas merci!!

  5. #5
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par jamsgoodon Voir le message
    Le but du jeu c'est de considérer toutes mes clefs 2 à 2 et chercher à savoir si (en terme de rang) elles se succèdent ou pas?
    Dans ce cas, tout mettre dans une map n'est pas une solution efficace... Le mieux est alors de garder les données dans un vecteur, et de l'indexer. Pour cela, tu fabriques un tableau d'index (vector<int>, contenant les rangs de 0 à n-1), et tu le tries (via sort) avec une fonction de comparaison qui compare les éléments de l'index sur la base des clefs (clef[idx[i]]<clef[idx[j], un truc comme ca).

    A la fin, tu as dans ton index le rang de chaque clef. C'est O(n lg n), donc nettement plus rapide que distance() (si sera quadratique)

    Francois

  6. #6
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 627
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 627
    Points : 30 692
    Points
    30 692
    Par défaut
    Salut,

    De plus, il faut bien être conscient du fait que, typiquement, une std::map est en réalité... un arbre binaire de recherche...

    Cela implique que, bien que les différents éléments soient affichés dans l'ordre, et que tu peux accéder à une clé particulière avec les crochets ( lamap[cle] ), les objet apparaissant dans l'ordre sont loins d'être contigus en mémoire, comme ca peut être le cas pour un vecteur.

    Ainsi, alors que tu as la certitude pour un vecteur qu'un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    type data = *(le_vecteur + N);
    est équivalent à un code du genre de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    type data = le_vecteur[N];
    tu ne peux absolument pas partir d'un préavis similaire avec la map

    Il y a de fortes chances pour que, si tu venais à écrire un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    type * ptr = &la_map[key];
    ++ptr;
    /*...*/
    ptr vienne à pointer... vers les marguerites dans lesquelles tu ne tardera pas à tomber

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    61
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 61
    Points : 43
    Points
    43
    Par défaut
    Citation Envoyé par fcharton Voir le message
    Dans ce cas, tout mettre dans une map n'est pas une solution efficace... Le mieux est alors de garder les données dans un vecteur, et de l'indexer. Pour cela, tu fabriques un tableau d'index (vector<int>, contenant les rangs de 0 à n-1), et tu le tries (via sort) avec une fonction de comparaison qui compare les éléments de l'index sur la base des clefs (clef[idx[i]]<clef[idx[j], un truc comme ca).

    A la fin, tu as dans ton index le rang de chaque clef. C'est O(n lg n), donc nettement plus rapide que distance() (si sera quadratique)

    Francois
    Bonjour, je n'ai pas tout compris du message.
    Le vecteur que tu me proposes de faire doit contenir quoi? les clefs et leur rang?

    j'ai fais une map qui marche pour l'instant.
    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
     
     
                                    for(map<int, string>::iterator EspDmFamElement = EspDmFam ->second.begin(); EspDmFamElement != EspDmFam ->second.end(); ++EspDmFamElement)
                                    {
                                          string espece = EspDmFam -> first; // espece;
                                          int debut_marqueur = EspDmFamElement -> first; // début_marqueur;
                                          fam = EspDmFamElement -> second; //famille
     
                                          //Test écriture;
                                          fichier3 << EspDmFam -> first;
                                          fichier3 <<" "<< debut_marqueur << " : ";
                                          fichier3 << EspDmFamElement -> second << endl;
     
                                           map<int, int> rangs; // creer map associant à chaque dm son rang : par espèce;
                                           rangs.insert (pair< int, int> (crang, EspDmFamElement-> first));
                                           fichier2 << espece << " le Dm " << EspDmFamElement -> first << " au rang " << crang <<" de la famille " << fam << endl;
                                           crang++;
     
    }

  8. #8
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    Ton approche via une map va fonctionner, c'est probablement la façon la plus simple de régler ton problème en utilisant les conteneurs de base de la STL.

    La version la plus simple est probablement quelque chose comme

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    map<string,int> TableDesRangs;
     
    for(int i=0;i<NbClefs;i++) TableDesRangs.insert(make_pair(Clef[i],0));
    // à ce stade tes clefs sont triées
    map<string,int>::iterator it;
    int nb=1; // si tes rangs commencent à 1
    for(it=TableDesRangs.begin();it!=TableDesRangs.end();it++) it->second=nb++;
    A ce stade TableDesRangs[clef] renvoie le rang de la clef (en base d'indice 1).

    Cette approche a plusieurs défauts :

    1- en insérant tes clefs dans une map, tu les tries, mais aussi tu construis un arbre de recherche binaire. Sur de grosses tables, ce n'est pas très efficace.
    2- si tu as plusieurs clefs de tri, il te faut autant de map que de clefs, c'est lourd
    3- pour trouver l'index d'une clef, il faut chercher dans la map, c'est logarithmique, mais ca peut ralentir (sur une table de mille clefs, ca fait 10 comparaisons par clef)
    4- (celui que signale Koala) une map, c'est moins pratique à gérer qu'un vector.

    L'approche par les index consiste à fabriquer un tableau qui te permet de retrouver le rang d'un élement de ta table d'origine. Dans la version usuelle, idx[0] te donne l'indice de la première clef, idx[1] l'indice de la seconde, etc... Il est alors facile de construire un tableau donnant les rangs, en faisant pour tout i

    Pour calculer l'index, c'est très simple, tu vas avoir quelque chose comme

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    vector<string> Clefs; // les clefs à indexer
    vector<int> idx; // ton tableau d'index
     
    // ceci va trier tes index dans l'ordre des clefs (c'est ça l'astuce)
    bool mycomp(const int &l,const int &r)
    {
    return Clefs[l]<Clefs[r];
    }
     
    // initialiser idx
    for(int i=0;i<NbClefs;i++) idx[i]=i;
    // l'indexation
    sort(idx.begin(),idx.end(),mycomp);
    Voila, pour parcourir ton tableau dans l'ordre des clefs, tu utilises Clefs[idx[i]].

    L'intérêt c'est que tu peux facilement manipuler plusieurs clefs différentes, des critères de tris compliqués, et que si tu n'as pas besoin de récopier tes clefs dans une map.

    Francois

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    61
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 61
    Points : 43
    Points
    43
    Par défaut
    Oui finalement, je vais utiliser les index, c'est claire que c'est mieux!
    Cependant pour mes Clefs ce ne sont pas des strings, ce sont des entiers. J'ai essayé d'adapter ce que vous m'avez dit mais en remplissant le vecteur Clefs, je reçois un message d'erreur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    no matching function for call to ‘std::vector<int, std::allocator<int> >::insert(int&)’|
    voici mon code sans les opérations. Je passerai aux opérations plustard.
    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
     
     
     for(map<string, map<int, string> >::iterator curEspece = FamillesTrieesParEspece.begin(); curEspece!= FamillesTrieesParEspece.end(); ++curEspece)
      {
     
                             for(map<int, string>::iterator it2 = curEspece ->second.begin(); it2 != curEspece->second.end(); ++it2)
                             {
     
                                int rang;
                                int i;
                                vector<int> Clefs; // les clefs à indexer
     
                                string espece = curEspece -> first;
                                int debut_marqueur = it2 -> first;
                                fichier3 << espece;
                                fichier3 <<" "<< debut_marqueur << " : ";
                                Clefs.insert(debut_marqueur);
                                vector<int> idx; // tableau d'index
                                rang[idx[i]]=i;
     
                            // ceci va trier tes index dans l'ordre des clefs (c'est ça l'astuce)
                            bool mycomp(const int &l,const int &r)
                            {
                            return Clefs[l]<Clefs[r];
                            }
     
                            // initialiser idx
                            for(int i=0;i<NbClefs;i++) idx[i]=i;
                            // l'indexation
                            sort(idx.begin(),idx.end(),mycomp);
     
     
                             }
     
     
                        }
    Aussi pour mes map d ça marche bien.
    Le seul souci c'est que ma map contient environ 14 000 clefs (1000 clef par espece, donc 14 especes) et le rang je ne le veux pas sur les 14 000 clefs. Mais je le veux plutôt pour chaque 1000 clefs associées à une des 14 espèces.

    En espérant que c'est pas lourd à comprendre tout ce que je raconte là!
    Merci d'avance.

    D'ailleurs voici le code.
    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
     
     for(map<string, map<int, string> >::iterator curEspece = FamillesTrieesParEspece.begin(); curEspece!= FamillesTrieesParEspece.end(); ++curEspece)
                        {
    map<int, int> LocalDm2Rang;
                string curEspeceName = curEspece -> first;
     
                uint rang = 0; // rang des Dm dans chaque espèce;
                for(map<int, string>::iterator curDm = curEspece ->second.begin(); curDm != curEspece ->second.end(); ++curDm){
     
                LocalDm2Rang.insert(pair< int, int> (curDm->first, rang));
                rang++;
     
                Dm2rangParEspece.insert(pair <string, map<int, int> > (curEspeceName , LocalDm2Rang));
     
                }
     
                    //Afficher la map associant Espèce Dm et Rang.
                    for(map<string, map<int, int> >::iterator it1 = Dm2rangParEspece.begin(); it1!= Dm2rangParEspece.end(); ++it1){
     
                        for(map<int, int>::iterator it2 = it1->second.begin(); it2 != it1->second.end(); ++it2){
     
                              fichier3 << it1 -> first;
                              fichier3 <<" "<< it2 -> first << " : ";
                              fichier3 << it2-> second << endl;
     
     
     
                        }
     
                    }
     
     
          }

  10. #10
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    61
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 61
    Points : 43
    Points
    43
    Par défaut
    Re Bonjour,

    Finalement y a tout qui marche!
    Et j'ai vérifié les résultats c'est logique, donc je pense que le mieux sereait d'en rester là avec mes map de map, qui sont tout de même géniales.

    Merci en tout cas!
    Voici le bout de code!

    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
     
    for(map<string, map<int, string> >::iterator curEspece = FamillesTrieesParEspece.begin(); curEspece!= FamillesTrieesParEspece.end(); ++curEspece)
            {
                map<int, int> LocalDm2Rang;
                string curEspeceName = curEspece -> first;
                unsigned int rang=0; // rang des Dm dans chaque espèce;
               // cout << " mise à zéro" << rang << endl;
     
                    for(map<int, string>::iterator curDm = curEspece ->second.begin(); curDm != curEspece ->second.end(); ++curDm){
                    LocalDm2Rang.insert(pair< int, int> (curDm->first, rang));
                    rang++;
                    //cout << " Le rang est " << rang << endl;
                    Dm2rangParEspece.insert(pair <string, map<int, int> > (curEspeceName , LocalDm2Rang));
     
                      fichier3 << curEspece -> first;
                      fichier3 <<" "<< curDm  -> first << " : ";
                      fichier3 << rang  << endl;
                    }
     
            }

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [FAQ] [jQuery] Comment puis-je changer l'ordre des éléments d'une liste ?
    Par SylvainPV dans le forum Contributions JavaScript / AJAX
    Réponses: 3
    Dernier message: 18/03/2014, 23h44
  2. Classement des éléments d'une liste par ordre alphabétique
    Par Cellendhyll82 dans le forum Débuter avec Java
    Réponses: 5
    Dernier message: 15/11/2010, 10h11
  3. Changer l'ordre des éléments d'une JList avec la souris
    Par rafalsh dans le forum Composants
    Réponses: 0
    Dernier message: 02/07/2009, 20h13
  4. Modification de l'ordre d'affichage des éléments d'une listview
    Par Onizuka-3 dans le forum VB 6 et antérieur
    Réponses: 0
    Dernier message: 24/02/2009, 11h47
  5. [C#] Inverser l'ordre des éléments d'une Hashtable
    Par lancer83 dans le forum Windows Forms
    Réponses: 10
    Dernier message: 31/08/2006, 20h03

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