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 :

Foncteurs et structures de données : partage des responsabilités.


Sujet :

C++

  1. #1
    Membre averti Avatar de Seabirds
    Homme Profil pro
    Post-doctoral fellow
    Inscrit en
    Avril 2015
    Messages
    294
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Post-doctoral fellow
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2015
    Messages : 294
    Points : 341
    Points
    341
    Par défaut Foncteurs et structures de données : partage des responsabilités.
    Salut à toutes et à tous !

    Me revoilà à gratouiller des conseils

    J'ai un type de données D à deux dimensions (spatial/temporel). Pour des raisons pratiques, il me paraissait mieux d'implémenter ça sous forme de vecteurs de vecteurs et non de matrices (j'ai essayé, c'était le bazar, j'ai fait demi-tour ).
    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
     
    class D
    {
        public:
            D();
            D(const std::string & name, const std::vector<std::vector<double> >& data);
            virtual ~D();
     
            // Read-Only Iteration along first dimension
            typedef std::vector<std::vector<double> >::const_iterator const_iterator;
            const_iterator begin() { return m_data.begin(); }
            const_iterator end() { return m_data.end(); }
     
        protected:
        private:
            std::string m_variableName;
            std::vector<std::vector<double> > m_data; 
            int m_spatialLength;
            int m_temporalLength;
    };
    Maintenant, j'aimerais appliquer un foncteur à chaque double contenu dans le champs m_data. Bon, y'a du foreach de foreach dans l'air, ça ça devrait aller.
    Mais j'ai du mal à intuiter (et googliser) sur qui doit faire quoi.

    Est-ce que c'est le foncteur qui décortique la donnée D avec des foreach pour finalement s'appliquer sur chacun des doubles, ou est-ce que c'est la donnée qui accueille un pointeur sur le foncteur pour descendre les dimensions et l'appliquer sur chaque double ?

    Infos:
    - m_data est assez gros, normalement constant, on a accès à D via un shared_ptr. Je ne sais pas trop quand le déférencer (ni même si je dois le faire).
    - le foncteur est une composition utilisable via un unique_ptr

    Merci d'avance de votre aide !
    Le débutant, lui, ignore qu'il ignore à ce point, il est fier de ses premiers succès, bien plus qu'il n'est conscient de l'étendue de ce qu'il ne sait pas, dès qu'il progresse en revanche, dès que s'accroît ce qu'il sait, il commence à saisir tout ce qui manque encore à son savoir. Qui sait peu ignore aussi très peu. [Roger Pol-Droit]
    Github
    Mon tout premier projet: une bibliothèque de simulation de génétique des populations

  2. #2
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2016
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Aube (Champagne Ardenne)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2016
    Messages : 6
    Points : 3
    Points
    3
    Par défaut
    Eh bien déjà, il y a un problème de constitude. Si tu donnes un const_iterator, il n'est pas possible de modifier ce sur quoi il itère. Donc il faudrait que tu aies une fonction map interne à la classe qui prenne en argument le foncteur pour l'appliquer; pour ma part je trouve ça un peu moche, mais c'est à toi de voir.

    Si tu décides de donner l'accès à l'extérieur ou que tu le fais de l'intérieur, ce n'est pas nécessaire de s'embarrasser avec foreach:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for (auto& v : m_data)
      for (auto& d : v) 
        mon_foncteur(d); // d = mon_foncteur(d) selon la sémantique de ton foncteur

    Les changements sont minimes en ajoutant la sémantique des pointeurs:

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for (auto& v : *monD)
      for (auto& d : v)
        (*mon_foncteur)(d);

    donc je vais essayé avec une switch

  3. #3
    Membre averti Avatar de Seabirds
    Homme Profil pro
    Post-doctoral fellow
    Inscrit en
    Avril 2015
    Messages
    294
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Post-doctoral fellow
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2015
    Messages : 294
    Points : 341
    Points
    341
    Par défaut
    Merci de ta réponse, j'y vois plus clair !
    Donc il faut obligatoirement modifier la collection sur laquelle on itère (ça veut dire qu'il faudra bien que je fasse un jour ou l'autre une copie de cette donnée partagée...).
    Je pensais reconstruire une autre collection à côté au fur et à mesure des itérations. C'est peut-être à la fois très moche est pas efficace du tout ?
    Le débutant, lui, ignore qu'il ignore à ce point, il est fier de ses premiers succès, bien plus qu'il n'est conscient de l'étendue de ce qu'il ne sait pas, dès qu'il progresse en revanche, dès que s'accroît ce qu'il sait, il commence à saisir tout ce qui manque encore à son savoir. Qui sait peu ignore aussi très peu. [Roger Pol-Droit]
    Github
    Mon tout premier projet: une bibliothèque de simulation de génétique des populations

  4. #4
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Points : 1 878
    Points
    1 878
    Billets dans le blog
    21
    Par défaut
    Sur l'efficacité, c'est sûr qu'une modification sur place est moins "chère" qu'une copie. Mais une copie est tout à fait une possibilité. Dans ce cas-là, tu peux utiliser std::transform :

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    template <typename Foncteur>
    std::vector<std::vector<double>> fmap_helper(const shared_ptr<D> old_d, Foncteur& fn) {
      std::vector<std::vector<double>> new_vec(old_d->end() - old_d->begin()); // à tout prendre faisons l'allocation mémoire d'un coup
      for (const auto& v : *old_d) {
        std::vector<double> ds(v.end()-v.begin()); // idem
        std::transform( v.begin(), v.end(), std::back_inserter(ds), fn);
        new_vec.emplace_back(std::move(ds)); // emplace_back et move semantics
      }
      return new_vec; // RVO optimisation
    }
     
    template <class Foncteur>
    std::shared_ptr<D> fmap(const shared_ptr<D> old_d, std::string nouveau_nom, Foncteur& fn)
      return std::make_shared<D>(nouveau_nom, fmap_helper(old_d, fn));
    }

  5. #5
    Membre averti Avatar de Seabirds
    Homme Profil pro
    Post-doctoral fellow
    Inscrit en
    Avril 2015
    Messages
    294
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Post-doctoral fellow
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2015
    Messages : 294
    Points : 341
    Points
    341
    Par défaut
    Glups

    On va prendre la modification sur place

    Mais merci beaucoup pour ta réponse !!!!
    Le débutant, lui, ignore qu'il ignore à ce point, il est fier de ses premiers succès, bien plus qu'il n'est conscient de l'étendue de ce qu'il ne sait pas, dès qu'il progresse en revanche, dès que s'accroît ce qu'il sait, il commence à saisir tout ce qui manque encore à son savoir. Qui sait peu ignore aussi très peu. [Roger Pol-Droit]
    Github
    Mon tout premier projet: une bibliothèque de simulation de génétique des populations

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Quitte à vouloir un truc performant, commence par ne pas utiliser de vector de vector.
    Quand tu auras un truc fonctionnel, on verra pour la performance.
    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 averti Avatar de Seabirds
    Homme Profil pro
    Post-doctoral fellow
    Inscrit en
    Avril 2015
    Messages
    294
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Post-doctoral fellow
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2015
    Messages : 294
    Points : 341
    Points
    341
    Par défaut
    Ah c'est pas bon ça un vecteur de vecteur ?
    Cela dit j'ai pris vector de vector justement pour que ce soit plus facile à manipuler pour moi... pas par souci d'efficacité
    Le débutant, lui, ignore qu'il ignore à ce point, il est fier de ses premiers succès, bien plus qu'il n'est conscient de l'étendue de ce qu'il ne sait pas, dès qu'il progresse en revanche, dès que s'accroît ce qu'il sait, il commence à saisir tout ce qui manque encore à son savoir. Qui sait peu ignore aussi très peu. [Roger Pol-Droit]
    Github
    Mon tout premier projet: une bibliothèque de simulation de génétique des populations

  8. #8
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Points : 1 878
    Points
    1 878
    Billets dans le blog
    21
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Quitte à vouloir un truc performant, commence par ne pas utiliser de vector de vector.
    Quand tu auras un truc fonctionnel, on verra pour la performance.
    Je suis d'accord dans la plupart des cas.
    Mais dans le cas où les vecteurs internes (à l'intérieur du vecteur de vecteurs) ne sont pas de même taille, cela reste le choix par défaut, n'est-ce pas?

  9. #9
    Membre averti Avatar de Seabirds
    Homme Profil pro
    Post-doctoral fellow
    Inscrit en
    Avril 2015
    Messages
    294
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Post-doctoral fellow
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2015
    Messages : 294
    Points : 341
    Points
    341
    Par défaut
    Mais dans le cas où les vecteurs internes (à l'intérieur du vecteur de vecteurs) ne sont pas de même taille, cela reste le choix par défaut, n'est-ce pas?
    ... chuuuut faut surtout pas dire qu'il est ABSOLUMENT nécessaire que les vecteurs internes soient tous de même tailles et que c'est peut être même ce qu'on appelle un invariant de classe que je voulais tester plus tard...
    Hum mais je suis sûr qu'on pouvait choisir une encore plus mauvaise solution non ?
    Le débutant, lui, ignore qu'il ignore à ce point, il est fier de ses premiers succès, bien plus qu'il n'est conscient de l'étendue de ce qu'il ne sait pas, dès qu'il progresse en revanche, dès que s'accroît ce qu'il sait, il commence à saisir tout ce qui manque encore à son savoir. Qui sait peu ignore aussi très peu. [Roger Pol-Droit]
    Github
    Mon tout premier projet: une bibliothèque de simulation de génétique des populations

  10. #10
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par stendhal666 Voir le message
    Je suis d'accord dans la plupart des cas.
    Mais dans le cas où les vecteurs internes (à l'intérieur du vecteur de vecteurs) ne sont pas de même taille, cela reste le choix par défaut, n'est-ce pas?
    Oui, mais quand on parle de matrices..
    Et même s'ils sont pas de même taille, si la taille est petite, il peut être plus intéressant de laisser des trous (valeurs vides/par défaut) que ça. Pour la simple raison des cache miss.
    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.

  11. #11
    Membre averti Avatar de Seabirds
    Homme Profil pro
    Post-doctoral fellow
    Inscrit en
    Avril 2015
    Messages
    294
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Post-doctoral fellow
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2015
    Messages : 294
    Points : 341
    Points
    341
    Par défaut
    Bah en fait les matrices j'ai tenté et j'ai trouvé ça assez malaisé à manipuler, mais je m'y suis sans doute mal pris.
    Le fait est que je dois faire au moins trois type d'opération :
    1- traverser toutes les valeurs d'une matrice pour la transformer et y appliquer un foncteur
    2- traverser simultanément plusieurs matrices en combinant leurs éléments par un foncteur, ce qui donne une autre matrice.
    3- traverser simultanément la même ligne de plusieurs matrices en combinant leurs éléments.

    Codé avec des matrices, au niveau algo c'était ok, mais soit que ce soit normal soit que je m'y sois mal pris j'ai trouvé ça pas très joli (je me suis payé quelques erreurs d'indiçage évidemment), donc j'ai voulu essayer avec des vecteurs. Mais évidemment, c'est pas joli pour autant

    [Edit] Et quand bien même j'utiliserais des matrices, va bien falloir que j'encapsule la matrice à un moment, et proposer une interface sympatoche permettant d'itérer sur la matrice, ça je sais pas faire
    Le débutant, lui, ignore qu'il ignore à ce point, il est fier de ses premiers succès, bien plus qu'il n'est conscient de l'étendue de ce qu'il ne sait pas, dès qu'il progresse en revanche, dès que s'accroît ce qu'il sait, il commence à saisir tout ce qui manque encore à son savoir. Qui sait peu ignore aussi très peu. [Roger Pol-Droit]
    Github
    Mon tout premier projet: une bibliothèque de simulation de génétique des populations

  12. #12
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Points : 1 878
    Points
    1 878
    Billets dans le blog
    21
    Par défaut
    1- traverser toutes les valeurs d'une matrice pour la transformer et y appliquer un foncteur
    2- traverser simultanément plusieurs matrices en combinant leurs éléments par un foncteur, ce qui donne une autre matrice.
    Dans ces deux cas, il n'y a aucune complexité supplémentaire à utiliser un simple vecteur représentant une matrice, puisque c'est précisément le parcours d'un itérateur.
    Dans les deux cas, l'algorithme standard std::transform peut-être utilisé (http://en.cppreference.com/w/cpp/algorithm/transform):

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    // cas 1
    using Matrix = std::vector<double>
    Matrix result;
    // NB: back_inserter renvoie un back_inserter_iterator qui écrit dans le conteneur qui lui est confié
    std::transform(matrix.begin(), matrix.end(), std::back_inserter(result), mon_foncteur);
     
    // cas 2
    Matrix result2;
    std::transform(matrixr.begin(), matrixr.end(), matrixl.begin(), std::back_inserter(result2), mon_foncteur_2);

    3- traverser simultanément la même ligne de plusieurs matrices en combinant leurs éléments.
    Là encore tu peux utiliser std::transform, après avoir calculé l'offset de départ et la longueur d'une ligne

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    // cas 3
    std::size_t indice_ligne = i * nb_colonnes // i est le numéro de la ligne
    std::transform(matrixl.begin()+indice_ligne, matrixl.begin()+indice_ligne+nb_colonnes, maxtrixr.begin()+indices_lignes, std::back_inserter(result3), mon_foncteur2);

    C'est donc assez harmonieux. La seule décision de conception difficile est de savoir si on enveloppe et comment envelopper le vecteur dans un type Matrix, pour mettre à disposition des fonctions comme: nombre_de_dimensions(), taille_dimension(unsigned dimension), et l'indexage: element_at(unsigned x, unsigned y).

    EDIT: je me rends compte que tu parles de "plusieurs" matrices et non de deux matrices. Cela étant, le principe est le même mais il faut faire ton propre algorithme, avec par exemple la signature:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    template <class InputIterator, class OutputIterator, class Foncteur>
    std::generalized_transform(InputIterator first, InputIterator last, std::vector<InputIterator> other_firsts, OutputIterator out, Foncteur& fn)

  13. #13
    Membre averti Avatar de Seabirds
    Homme Profil pro
    Post-doctoral fellow
    Inscrit en
    Avril 2015
    Messages
    294
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Post-doctoral fellow
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2015
    Messages : 294
    Points : 341
    Points
    341
    Par défaut
    Merci beaucoup de ta réponse je vais regarder tout ça et ajuster mon code en fonction de ça !!!

    La seule décision de conception difficile est de savoir si on enveloppe et comment envelopper le vecteur dans un type Matrix, pour mettre à disposition des fonctions comme: nombre_de_dimensions(), taille_dimension(unsigned dimension), et l'indexage: element_at(unsigned x, unsigned y).
    Vi, bien d'accord, j'en parlais d'ailleurs dans un edit de mon message précédent qui s'est croisé avec ta réponse.

    Quelles peuvent être les raisons poussant à ne pas cacher le vecteur dans une classe ? Y'a un moment j'avais hésité à hériter de vecteur (ou matrice ou autre ...) mais après quelques recherches les gens semblaient plutôt dire "surtout pas".
    Le débutant, lui, ignore qu'il ignore à ce point, il est fier de ses premiers succès, bien plus qu'il n'est conscient de l'étendue de ce qu'il ne sait pas, dès qu'il progresse en revanche, dès que s'accroît ce qu'il sait, il commence à saisir tout ce qui manque encore à son savoir. Qui sait peu ignore aussi très peu. [Roger Pol-Droit]
    Github
    Mon tout premier projet: une bibliothèque de simulation de génétique des populations

  14. #14
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Points : 1 878
    Points
    1 878
    Billets dans le blog
    21
    Par défaut
    Quelles peuvent être les raisons poussant à ne pas cacher le vecteur dans une classe ? Y'a un moment j'avais hésité à hériter de vecteur (ou matrice ou autre ...) mais après quelques recherches les gens semblaient plutôt dire "surtout pas".
    Il n'y a pas de raison universelle à ne pas hériter d'un vecteur. Il me semble qu'il n'a pas de destructeur virtuel et que cela poserait problème si quelqu'un décide d'abord d'écrire:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    std::vector<double>* vp = new Matrix();
    Alors:
    [CODE+C++]delete vp;[/CODE]
    n'appellera pas le destructeur de Matrix, ce qui pourrait causer une fuite de mémoire.

    Tu peux hériter de façon privée de vector pour éviter cet usage, et rendre public les fonctions de vector avec une directive using:

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class MaMatrice : private std::vector<double> {
      public:
        using std::vector<double>::begin;
        using std::vector<double>::end;
        // et toute autre fonction que tu veux rendre accessible
    }

    Le mieux est de limiter au maximum l'interface exposée, mais ce sont plutôt des considérations générales.

    Enfin la possibilité de contenir un vecteur n'est pas nécessairement désagréable à l'usage:

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class MaMatrice {
      public: 
        std::vector<double> data;
        double& element_at(std::size_t x, std::size_t y);
        ...
    }
     
    MaMatrice m;
    double d = m.data[i];
    double d2 = m.element_at(j, k);

    Mais bon, si le tout est pour un projet perso et que tu veux te faciliter la vie, tu peux hériter publiquement de vector -mais ce n'est pas une bonne pratique.

  15. #15
    Membre averti Avatar de Seabirds
    Homme Profil pro
    Post-doctoral fellow
    Inscrit en
    Avril 2015
    Messages
    294
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Post-doctoral fellow
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2015
    Messages : 294
    Points : 341
    Points
    341
    Par défaut
    Pfiou, merci de vous acharner à me faire comprendre des évidences...
    A charge de revanche quand j'aurais gagné des points d'XP.

    Je pense que vous m'avez filé assez d'info pour que je mette le sujet en résolu et que je bricole tout ça !
    Cordialement,

    [Edit]
    Après bricolage, j'ai fini par définir une classe encapsulant un vecteur, en proposant suffisament d'itérateurs pour pouvoir itérer dessus de manière suffisante à mes besoins, et plus ou moins transparente. C'est pas parfait, mais ça compile, ça semble pas faire n'importe quoi. Encore un grand merci pour toutes vos suggestions !

    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
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    #include <iostream>
    #include <string>
    #include <vector>
    #include <algorithm>    // std::transform
     
    using namespace std;
     
    class SpatioTemporalDataSet
    {
        public:
            SpatioTemporalDataSet(const std::string & name, std::size_t nbDemes, std::size_t nbTimeSteps,  std::vector<double>& data);
            virtual ~SpatioTemporalDataSet();
     
            typedef std::vector<double>::iterator iterator;
            iterator begin() { return m_data.begin(); }
            iterator end() { return m_data.end(); }
     
            typedef std::vector<double>::const_iterator const_iterator;
            const_iterator begin() const { return m_data.begin(); }
            const_iterator end() const { return m_data.end(); }
     
     
            // STL non constant iterator to iterate over a same temporal step
            iterator begin(std::size_t time) { return m_data.begin() + (time)*m_nbrOfDemes ; }
            iterator end(std::size_t time) { return begin(time + 1) ; }
     
            // STL constant iterator to iterate over a same temporal step
            const_iterator begin(std::size_t time) const { return m_data.begin() + (time)*m_nbrOfDemes ; }
            const_iterator end(std::size_t time) const { return begin(time + 1) ; }
     
            // Getters
            int GetNumberOfDemes(void) const { return m_nbrOfDemes; }
            int GetNumberOfTimeSteps(void) const { return m_nbrOfTimeSteps; }
            std::string GetNameOfEnvironmentalVariable(void) const { return m_name; }
     
        private:
            std::vector<double> m_data;
            std::string m_name;
            std::size_t m_nbrOfDemes;
            std::size_t m_nbrOfTimeSteps;
    };
     
    SpatioTemporalDataSet::SpatioTemporalDataSet(const std::string & name, std::size_t nbDemes, std::size_t nbTimeSteps,  std::vector<double>& data) :
    m_data(data),
    m_name(name),
    m_nbrOfDemes(nbDemes),
    m_nbrOfTimeSteps(nbTimeSteps)
    {}
     
    SpatioTemporalDataSet::~SpatioTemporalDataSet(){}
     
    double op_increase (double i) { return i += 1; }
     
    int main()
    {
        vector<double> v = {1,2,3,4,5,6,7,8,9,10,11,12};
        SpatioTemporalDataSet dataSet("pluviometry", 4, 3, v);
     
        std::cout << "This is a spatio-temporal dataSet for "
        << dataSet.GetNameOfEnvironmentalVariable() << " with "
        << dataSet.GetNumberOfDemes() << " demes and "
        << dataSet.GetNumberOfTimeSteps() << " time steps "
        << std::endl;
     
        // Print all values :
        for (std::vector<double>::const_iterator i = dataSet.begin(); i != dataSet.end(); ++i)
            std::cout << *i << ' ';
     
        std::cout << std::endl;
     
        for (auto i : dataSet) // works too
            std::cout << i << ' ';
     
        std::cout << std::endl;
     
        // Access temporal steps one by one:
        for (std::vector<double>::const_iterator i = dataSet.begin(0); i != dataSet.end(0); ++i) // and not 0 : need an assert
            std::cout << *i << ' ';
     
        std::cout << std::endl;
     
        for (std::vector<double>::const_iterator i = dataSet.begin(1); i != dataSet.end(1); ++i)
            std::cout << *i << ' ';
     
        std::cout << std::endl;
     
        for (std::vector<double>::const_iterator i = dataSet.begin(2); i != dataSet.end(2); ++i)
            std::cout << *i << ' ';
     
        std::cout << std::endl;
     
        // Add 1 for all data
        std::vector<double> bar;
        int d = dataSet.GetNumberOfDemes();
        int t = dataSet.GetNumberOfTimeSteps();
        bar.resize(d*t); // allocate space
        transform (dataSet.begin(), dataSet.end(), bar.begin(), op_increase);
     
        for (auto i : bar) // works too
            std::cout << i << ' ';
     
        std::cout << std::endl;
        cout << "Hello world!" << endl;
        return 0;
    }
    Le débutant, lui, ignore qu'il ignore à ce point, il est fier de ses premiers succès, bien plus qu'il n'est conscient de l'étendue de ce qu'il ne sait pas, dès qu'il progresse en revanche, dès que s'accroît ce qu'il sait, il commence à saisir tout ce qui manque encore à son savoir. Qui sait peu ignore aussi très peu. [Roger Pol-Droit]
    Github
    Mon tout premier projet: une bibliothèque de simulation de génétique des populations

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

Discussions similaires

  1. Quelle structure de données ? Analyse des occurrences d'un trigramme
    Par Tidus159 dans le forum Algorithmes et structures de données
    Réponses: 46
    Dernier message: 12/04/2009, 19h35
  2. VmWare sous XP: partager des données avec Linux
    Par EvilAngel dans le forum VMware
    Réponses: 18
    Dernier message: 06/01/2009, 13h03
  3. Réponses: 9
    Dernier message: 15/12/2006, 11h29
  4. Réponses: 3
    Dernier message: 11/12/2006, 12h18

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