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

SL & STL C++ Discussion :

Utiliser vector::erase avec le résultat d'un remove_copy_if


Sujet :

SL & STL C++

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    68
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 68
    Par défaut Utiliser vector::erase avec le résultat d'un remove_copy_if
    Bonjour,

    Voilà ce problème est peut-être tout à fait basique mais j'ai beaucoup cherché je ne trouve pas la solution. Il s'agit d'effacer les élément d'un container qui répondent à un prédicat, tout en les copiant dans un autre vecteur. En regardant la doc de la STL on pourrait croire que c'est très simple en voyant le nom des fonctions vector::erase et remove_copy_if. Seulement ce dernier algo, contrairement à remove_if, renvoie un output iterator, ce qui m'empêche de faire comme avec un remove_if :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    v.erase(remove_copy_if(v.begin(), v.end(), [output], [predicat]), v.end()); // ne compile pas
    Tous les exemples vu sur le net balancent les objets supprimés dans cout, ce qui ne m'apporte pas grand chose...

    Je suis donc obligé, chaque fois que je veux faire ça, de passer par des moyens détournés, du type : le foncteur qui sert de prédicat se charge de mettre dans une liste les objets pour lesquels son operator() renvoie true, et cette liste sera ensuite récupérée. Pour des problèmes un peu plus complexes, cette solution complique énormément le code. De plus, elle casse le principe 1 classe = 1 responsabilité.

    Y a-t-il une solution pour utiliser le résultat d'un remove_copy_if avec un vector::erase, ou pour atteindre d'une autre façon l'objectif initial de façon "relativement" directe ?

    Merci d'avance

  2. #2
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    A mon avis il faudra le faire en deux fois, car à ma connaissance remove_copy_if ne fait pas le boulot de remove (ie. il ne déplace pas les éléments vérifiant le prédicat à la fin de la séquence).

    Donc perso je ferais un remove_copy_if, suivi d'un erase-remove, avec le même prédicat pour les deux.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    68
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 68
    Par défaut
    En fait je m'aperçois que ma question était mal posée car elle ne ciblait pas le bon problème (à force de faire des tests dans tous les sens, je finis par ne plus savoir ce qui me pose réellement problème).

    L'output iterator retourné par le remove_copy_if m'a en effet posé problème pour l'utiliser après sur un erase, mais comme tu le dis on peut s'en sortir en 2 passes, même si ça implique 2 parcours, ça ne plombera sûrement pas beaucoup mes perfs. Mais mon 2è problème (vraiment bloquant celui-là) avec cet output iterator est que je ne sais pas du tout comment l'utiliser pour "alimenter" un autre vecteur afin d'y récupérer les élements supprimés. Je pense qu'il s'agit d'une bête lacune dans mes connaissances... comment fait-on ça ? Certes je pourrais le faire avec un for et un if, mais je suppose que remove_copy_if sert précisément à ça...

  4. #4
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Etant du même type que l'itérateur passé pour stocker le résultat, je pense que le retour de remove_copy_if est un itérateur qui pointe vers la fin de la copie. Donc ce n'est pas exploitable pour ce que tu veux faire.

    Pourquoi ne pas utiliser plutôt le retour de remove, qui lui pointera vers le début des éléments supprimés ?

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    68
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 68
    Par défaut
    Ben justement c'est ce que je voulais faire au départ car je n'avais pas compris le fonctionnement de remove. Je pensais que cet algo :
    - déplaçait en début de conteneur les éléments qui ne vérifient pas le prédicat
    - déplaçait à la fin ceux qui y répondent

    Or il ne fait que la première étape (la deuxième serait une perte de temps), donc les éléments qui vérifient le prédicat sont invalidés. Le programme suivant :

    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
    	vector<int> v;
     
    	v.push_back(1);
    	v.push_back(2);
    	v.push_back(3);
    	v.push_back(1);
    	v.push_back(2);
    	v.push_back(3);
    	v.push_back(1);
    	v.push_back(2);
    	v.push_back(3);
     
    	remove(v.begin(), v.end(), 2);
     
    	for (vector<int>::iterator i=v.begin(); i!=v.end(); ++i)
    		cout << *i;
    Retourne ceci :
    Autrement dit il a copié tous les 1 et 3 au début, mais il n'a pas cherché à conserver les 2. Les derniers éléments sont restés inchangés (123).

    Je ne sais donc toujours pas comment récupérer les éléments qui vérifient mon prédicat. Et je finis aussi par me demander à quoi peut bien servir remove_copy si vraiment :
    - il ne sert pas à supprimer les éléments dans le vecteur source (pas de remove)
    - il ne sert pas à les mettre dans un vecteur cible (pas de copy)

    J'ai bien essayé de mettre un back_inserter(vecteurcible) en 3è param de remove_copy_if, mais j'obtiens alors la liste.... des éléments non supprimés !

    Si quelqu'un a une idée... je ne peux me résoudre au fait que la STL ne sache pas faire une manip donc on a besoin aussi fréquemment.

  6. #6
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Par défaut
    Regarde plutôt du côté de partition alors remove, ça efface les éléments
    parition, ça coupe le conteneur en 2.

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    68
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 68
    Par défaut
    Wow génial ! C'est exactement ce qu'il me fallait... je savais que c'était une lacune dans mes connaissance. Je connaissais pas cet algo et malgré que j'aie parcouru plusieurs fois tous les algos de <algorithm>, je ne m'étais pas du tout arrêté sur celui-là.

    Merci !

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

Discussions similaires

  1. Réponses: 13
    Dernier message: 18/10/2006, 16h09
  2. Utiliser DirectX 9 avec C++Builder
    Par Olivier Constans dans le forum DirectX
    Réponses: 2
    Dernier message: 27/06/2005, 11h30
  3. utilisation de dll avec diverses compilateurs
    Par Thylia dans le forum C++
    Réponses: 30
    Dernier message: 21/10/2004, 16h30
  4. utilisation de fetch avec select
    Par arwen dans le forum MS SQL Server
    Réponses: 5
    Dernier message: 06/06/2003, 10h03
  5. Utiliser Borland C++ avec Emacs sous Windows
    Par Eikichi dans le forum Autres éditeurs
    Réponses: 2
    Dernier message: 02/03/2003, 08h40

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