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 :

[STL][algorithm]for_each vs transform


Sujet :

SL & STL C++

  1. #1
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut [STL][algorithm]for_each vs transform
    Bonjour tout le monde,

    Je veux faire une fonction qui prend une string et qui la met en majuscule (nous ignorerons ici les problèmes d'indianness, d'accents et de ponctuation).

    J'ai trouvé 2 façons pour le faire. La première utilise la fonction for_each:
    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
    #include <string>
    #include <algorithm>
    //...
    using namespace std;
     
    class MyUpper1
    {
    public:
    	MyUpper1(string& str):str_(str){}
    	void operator () (char c) const
    	{
    		str_ += toupper(c);
    	}
     
    private:
    	string& str_;
    };
     
    int main()
    {
    	string str = "test";
    	string result1;
    	for_each( str.begin(), str.end(), MyUpper1(result1) );
    //...
    }
    La deuxième solution utilise la fonction transform:
    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
    #include <string>
    #include <algorithm>
    //...
    using namespace std;
     
    class MyUpper2
    {
    public:
    	char operator () (char c)
    	{
    		return toupper(c);
    	}
    };
     
    int main()
    {
    	string str = "test";
    	string result2 = str;
    	transform( str.begin(), str.end(), result2.begin(), MyUpper2() );
    //...
    }
    Je pense que les 2 méthodes sont assez proches, car elles utilisent toute les deux une boucle du type
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for (; _ChkFirst != _ChkLast; ++_ChkFirst)
    mais si les deux façons de faire existent, c'est qu'il doit y a voir des différences. Non?
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  2. #2
    Membre éclairé Avatar de befalimpertinent
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    561
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Avril 2007
    Messages : 561
    Points : 833
    Points
    833
    Par défaut
    La version avec for_each marche ?
    J'ai toujours pensé que for_each ne pouvait pas modifier les valeurs du container et que transform lui le pouvait
    Linux > *

  3. #3
    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 : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    for_each applique un traitement prenant en paramètre les éléments, mais celui-ci peut faire tout autre chose qu'agir sur ceux-ci. Par exemple je pourrais afficher les éléments à l'écran.

    transform par contre demande à ce que le traitement produise un résultat, et place celui-ci dans un autre conteneur.

    Donc ici tu peux faire avec les deux, mais ce n'est pas toujours le cas.

  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 : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    J'ai toujours pensé que for_each ne pouvait pas modifier les valeurs du container
    Il ne le fait pas. Par contre rien n'empêche ton foncteur de mettre à jour un autre conteneur avec les éléments reçus, comme ici.

    et que transform lui le pouvait
    En fait il ne fait que placer le résultat dans un autre conteneur. En pratique il se trouve que si destination = source, ça va modifier les valeurs.

  5. #5
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Hum... je ne comprend pas trop
    Laurent, aurais-tu un exemple de quelque chose que je puisse faire avec avec transform et pas avec for_each et/ou l'inverse?
    J'ai essayé d'en trouver, mais sans succés.

    En revanche, il est clair que dans certains car, l'un sera plus pratique que l'autre, mais je ne vois pas d'exemples où l'un permet de faire quelque chose que l'autre ne permet pas.
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  6. #6
    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 : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Un exemple simple pour lequel transform serait hors-sujet :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    struct A
    {
        void F() {std::cout << "salut" << std::endl;}
    };
     
    int main()
    {
        std::vector<A> v(3);
     
        std::for_each(v.begin(), v.end(), std::mem_fun_ref(&A::F));
    }
    Ici on veut juste appliquer un traitement sur chaque élément, mais on n'attend aucun retour.

    Pour l'exemple inverse, c'est inutile car on pourra toujours émuler un transform avec un for_each dont le foncteur prendra en paramètre le conteneur à mettre à jour. C'est juste que c'est inutile, et que transform le fait tout seul.

  7. #7
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Ok je commence à comprendre.

    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

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

Discussions similaires

  1. Réponses: 7
    Dernier message: 19/02/2010, 09h42
  2. [STL] for_each et transform
    Par yan dans le forum SL & STL
    Réponses: 29
    Dernier message: 03/08/2007, 00h20
  3. [STL] tutoriels sur for_each, transform, foncteur
    Par yan dans le forum SL & STL
    Réponses: 4
    Dernier message: 26/07/2007, 13h41
  4. Problème lors de la transformation de mon "algorithm&qu
    Par prunodagen dans le forum Langage SQL
    Réponses: 8
    Dernier message: 27/04/2005, 21h48

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