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 :

std::map, effacer des éléments suivant un critère donné


Sujet :

C++

  1. #1
    Débutant
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    688
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 688
    Points : 176
    Points
    176
    Par défaut std::map, effacer des éléments suivant un critère donné
    Salut,

    Quel est la bonne façon de faire pour effacer des éléments dans une map, suivant un critère du type chaine == "valeur".

    Est ce que cette façon est correct et performante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
            std::map<std::string,S>::const_iterator it;
            for(it=mapS.begin();it!=mapS.end();)
            {
                if( it->second.var41 == id )
                {
                    mapS.erase( it );
                }
                else
                    ++it;
            }
    y a t-il mieux?

    Merci.

  2. #2
    Membre confirmé Avatar de Lavock
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    560
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 560
    Points : 633
    Points
    633
    Par défaut
    Erase à besoin d'un iterator, pas d'un const_iterator.

    Ben c'est pas "mal", mais le concept est étrange... (et au passage certain vont raller car tu ne respect pas Demeter, mais c'est une autre histoire).

    D'habitude, la version erase(iterator) est peu utiliser. Mais alors là, parcourir la map jusqu'à trouver le bon... Quel est l'intérêt de la map ?
    The mark of the immature man is that he wants to die nobly for a cause, while the mark of the mature man is that he wants to live humbly for one.
    --Wilhelm Stekel

  3. #3
    Débutant
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    688
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 688
    Points : 176
    Points
    176
    Par défaut
    J'utilise plusieurs map.
    Une entrée d'une mapA peut contenir (entre autre) la clef d'une autre mapB.

    j'ai défois besoin d'effacer la clef de la mapB, ainsi que toutes les entrées des autres map qui contiennent cette clef

  4. #4
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    Citation Envoyé par guillaume07 Voir le message
    y a t-il mieux?
    std::remove_if avec le bon prédicat.

  5. #5
    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
    Citation Envoyé par guillaume07 Voir le message
    Est ce que cette façon est correct et performante
    Presque correcte, la version idiomatique est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    for(; iter != endIter; ) 
    { 
       if(Some Condition) 
       { 
          aMap.erase(iter++); 
       } 
        else 
       { 
          ++iter; 
      } 
    }
    Citation Envoyé par 3DArchi
    std::remove_if avec le bon prédicat.
    Je ne crois pas qu'un remove_if (qui ne fait que déplacer des éléments) peut s'appliquer à une map.

  6. #6
    Débutant
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    688
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 688
    Points : 176
    Points
    176
    Par défaut
    Citation Envoyé par Arzar Voir le message
    Presque correcte, la version idiomatique est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    for(; iter != endIter; ) 
    { 
       if(Some Condition) 
       { 
          aMap.erase(iter++); 
       } 
        else 
       { 
          ++iter; 
      } 
    }


    Je ne crois pas qu'un remove_if (qui ne fait que déplacer des éléments) peut s'appliquer à une map.
    perso, j'avais également ça en tête.

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    87
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Avril 2008
    Messages : 87
    Points : 111
    Points
    111
    Par défaut
    Il manquait au standard 98 le retour de l'itérateur suivant à l'operation erase() de std::map. Il a été rajouté au standard 03. C'est déjà pris en compte dans les unordered de boost. (attenion gcc/visual divergent aussi)
    remove_if ne devrait pas s'appeller comme ca car il ne fait pas du tout ce qu'on croit.

  8. #8
    Débutant
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    688
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 688
    Points : 176
    Points
    176
    Par défaut
    Citation Envoyé par Arzar Voir le message
    Presque correcte, la version idiomatique est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    for(; iter != endIter; ) 
    { 
       if(Some Condition) 
       { 
          aMap.erase(iter++); 
       } 
        else 
       { 
          ++iter; 
      } 
    }
    .
    pourquoi ne pas farie ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
     
    for(; iter != endIter; ) 
    { 
       if(Some Condition) 
       { 
          aMap.erase(iter); 
       } 
     
       ++iter; 
     
    }

  9. #9
    Membre confirmé Avatar de Lavock
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    560
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 560
    Points : 633
    Points
    633
    Par défaut
    Citation Envoyé par guillaume07
    pourquoi ne pas farie ça
    Hum :

    Citation Envoyé par Lightness1024 Voir le message
    Il manquait au standard 98 le retour de l'itérateur suivant à l'operation erase() de std::map. Il a été rajouté au standard 03. C'est déjà pris en compte dans les unordered de boost. (attenion gcc/visual divergent aussi)
    remove_if ne devrait pas s'appeller comme ca car il ne fait pas du tout ce qu'on croit.
    <=>

    Si norme > c++98, faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
     
    for(; iter != endIter; ++iter) 
    { 
       if(Some Condition)  
          aMap.erase(iter);   
    }
    sinon faire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
     
    for(; iter != endIter; ) 
    { 
       if(Some Condition) 
          aMap.erase(iter++); 
     
       else
           ++iter; 
    }
    Autrement dit, avant 2003, erase invalidé l'itérateur.
    The mark of the immature man is that he wants to die nobly for a cause, while the mark of the mature man is that he wants to live humbly for one.
    --Wilhelm Stekel

  10. #10
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Arzar Voir le message
    Je ne crois pas qu'un remove_if (qui ne fait que déplacer des éléments) peut s'appliquer à une map.
    Effectivement, j'aurais mieux fait de faire tourner 7 fois mon pouce autour de l'autre avant de répondre. On va mettre ça sur le dos d'une digestion soporifique.

  11. #11
    Débutant
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    688
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 688
    Points : 176
    Points
    176
    Par défaut
    Citation Envoyé par Lavock Voir le message
    Hum :



    <=>

    Si norme > c++98, faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
     
    for(; iter != endIter; ++iter) 
    { 
       if(Some Condition)  
          aMap.erase(iter);   
    }
    sinon faire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
     
    for(; iter != endIter; ) 
    { 
       if(Some Condition) 
          aMap.erase(iter++); 
     
       else
           ++iter; 
    }
    Autrement dit, avant 2003, erase invalidé l'itérateur.
    ty

  12. #12
    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
    Citation Envoyé par Lavock Voir le message
    Autrement dit, avant 2003, erase invalidé l'itérateur.
    Mais après 2003 aussi !
    Avant 2003 il fallait faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    for(; iter != endIter; ) 
    { 
       if(Some Condition) 
          aMap.erase(iter++); 
        else
           ++iter; 
    }
    Après 2003, on peut maintenant faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    for(; iter != endIter; ) 
    { 
       if(Some Condition) 
          iter = aMap.erase(iter); 
        else
           ++iter; 
    }
    La correction de 2003 a permis d'aligner la méthode erase des map avec celles des autres conteneurs - en renvoyant l'itérateur valide qui suit celui venant d'être tout juste invalidé.

    Et tant mieux, car le trick du aMap.erase(iter++) en C++98 était vraiment pas évident.

  13. #13
    Membre confirmé Avatar de Lavock
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    560
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 560
    Points : 633
    Points
    633
    Par défaut
    Au temps pour moi, le prototype est bien iterator erase(iterator), et non void erase(iterator) >< !
    The mark of the immature man is that he wants to die nobly for a cause, while the mark of the mature man is that he wants to live humbly for one.
    --Wilhelm Stekel

Discussions similaires

  1. [Joomla!] Effacer des modules suivant la section
    Par lovoo dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 1
    Dernier message: 22/08/2008, 01h33
  2. [multi map] supprimer des éléments
    Par poukill dans le forum SL & STL
    Réponses: 3
    Dernier message: 22/05/2007, 12h17
  3. [multi map] supprimer des éléments
    Par poukill dans le forum C++
    Réponses: 3
    Dernier message: 22/05/2007, 12h17
  4. Effacer des éléments sur click
    Par hugo1992 dans le forum AWT/Swing
    Réponses: 3
    Dernier message: 22/03/2007, 16h22
  5. Effacer des éléments graphiques
    Par benjiprog dans le forum AWT/Swing
    Réponses: 4
    Dernier message: 08/09/2006, 13h44

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