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 :

question sur set_intersection


Sujet :

SL & STL C++

  1. #1
    Membre éclairé
    Inscrit en
    Mai 2006
    Messages
    330
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 330
    Par défaut question sur set_intersection
    Salut,

    Je veux l'utiliser pour faire l'intersection entre 2 std::set<std::string> dont les tailles sont par exemple 3 et 4. Ma question concerne l'iterateur de résultat qu'on donne en 5ème argument à la fonction.
    J'ai créé un résultat std::set<std::string> result;
    Dois-je redimensionner result en prévoyant une taille maximale de 3 ou bien je peux me contenter de donner result.begin() et il se débrouillera tout seul pour y insérer des éléments ?

    Merci

  2. #2
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 306
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 306
    Billets dans le blog
    2
    Par défaut
    Bonjour,

    je ne suis pas trés à l'aise avec set_intersection, mais le code suivant pourra peut-être t'aider:
    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
    //je commence par remplir 2 sets s1 et s2
    std::set<std::string> s1;
    s1.insert("toto");
    s1.insert("titi");
    s1.insert("tata");
     
    std::set<std::string> s2;
    s2.insert("tutu");
    s2.insert("toto");
    s2.insert("titi");
    s2.insert("tyty");
     
    // je prépare s3 qui va récupérer le résultat le l'intersection.
    std::set<std::string> s3;
    // je copie le plus grand set (entre s1 et s2) dans s3
    s3 = ( s1.size()>s2.size() ) ? s1 : s2;
    // je remplis s3 de chaînes vide
    std::fill(s3.begin(), s3.end(), "");
     
    // j'applique set_intersection
    std::set<std::string>::iterator it = std::set_intersection(s1.begin(), s1.end(), s2.begin(), s2.end(), s3.begin() );
     
    //je "retaille" s3 de façon à ce que les éléments superflux soient supprimés
    std::set<std::string>(s3.begin(), it ).swap(s3);
    Pour répondre à ta question: oui, il faut pré-allouer le set dans lequel tu vas mettre le résultat.

  3. #3
    Membre éclairé
    Inscrit en
    Mai 2006
    Messages
    330
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 330
    Par défaut
    Merci, ça répond effectivement parfaitement à ma question.
    En fait pour ce cas précis je me fous complètement de connaître l'intersection, tout ce qui m'intéresse c'est de savoir si elle est vide ou pas. C'est pourquoi je trouve assez rébarbatif de devoir faire autant de choses sur une variable que je n'utilise pas en fin de compte... Connaissez vous un façon aussi fiable mais plus directe d'obtenir l'info ?

  4. #4
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 306
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 306
    Billets dans le blog
    2
    Par défaut
    Si j'ai bien compris, tu veux juste tester s'il existe au moins un élément commun entre deux conteneurs.
    Si c'est le cas, je pense que le plus simple est d'utiliser la fonction find_first_of (déclarée, à l'instar de set_intersection, dans l'en-tête <algorithm>):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    std::set<std::string> s1;
    std::set<std::string> s2;
     
    //... remplissage de s1 et s2
     
    std::set<std::string>::iterator it = std::find_first_of(s1.begin(), s1.end(), s2.begin(), s2.end() );
    if (it==s1.end()) // si (it==s1.end()) cela signifie qu'aucun élément n'est commun à s1 et s2
    {
    //code
    }
    else // sinon cela signifie qu'il existe au moins 1 élément commun
    {
    //code
    }
    Hope it helps.

  5. #5
    Membre éclairé
    Inscrit en
    Mai 2006
    Messages
    330
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 330
    Par défaut
    Citation Envoyé par r0d Voir le message
    Si j'ai bien compris, tu veux juste tester s'il existe au moins un élément commun entre deux conteneurs.
    Oui c'est ça. Je suppose que la version find_first_of est plus efficace...

  6. #6
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 306
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 306
    Billets dans le blog
    2
    Par défaut
    Beaucoup plus efficace en effet, et plus simple à écrire

  7. #7
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Sauf que find_first_of est de complexité O(n1*n2), alors qu'un set_intersection est de complexité O(n1+n2), donc à part si les deux set ont en général beaucoup d'éléments communs (dans ce cas, le find s'arrêtera vite), le set_intersection sera bien plus rapide.

    Bien entendu, le plus rapide consisterait à faire une sorte de find_first_of utilisant le fait que les séquences sont triées, qui est une information très intéressante, probablement d'ailleurs en s'inspirant de l'algo de set_intersection et en ajoutant un court circuit dès qu'un élément commun est trouvé.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  8. #8
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 306
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 306
    Billets dans le blog
    2
    Par défaut
    En effet. Je te remercie pour cette précision, et ça me donne un élément de réponse pour une question que je me pose depuis quelque temps: a quoi servent les algo set_intersection, set_difference, set_union, etc. ?

  9. #9
    Membre émérite Avatar de HanLee
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Par défaut
    Citation Envoyé par r0d Voir le message
    En effet. Je te remercie pour cette précision, et ça me donne un élément de réponse pour une question que je me pose depuis quelque temps: a quoi servent les algo set_intersection, set_difference, set_union, etc. ?
    Ben... en théorie des ensembles t'as jamais manipulé l'intersection, la différence et l'union de 2 ensembles ?

  10. #10
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 306
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 306
    Billets dans le blog
    2
    Par défaut
    Si, mais ce que je veux dire, c'est que je trouve que ces fonctions sont tellement mal définies qu'elle sont inutilisables telles qu'elles. Ce topic en est un exemple parfait: on ne sait pas à l'avance combien d'éléments vont être communs à nos deux conteneurs. Donc si je devais faire une intersection entre deux set, je le ferais via un foncteur qui utilise un insert et qui serait appelé par une boucle for_each, plutôt que d'utiliser un set_intersection.

  11. #11
    Membre émérite Avatar de HanLee
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Par défaut
    Citation Envoyé par r0d Voir le message
    Si, mais ce que je veux dire, c'est que je trouve que ces fonctions sont tellement mal définies qu'elle sont inutilisables telles qu'elles. Ce topic en est un exemple parfait: on ne sait pas à l'avance combien d'éléments vont être communs à nos deux conteneurs. Donc si je devais faire une intersection entre deux set, je le ferais via un foncteur qui utilise un insert et qui serait appelé par une boucle for_each, plutôt que d'utiliser un set_intersection.
    En fait la bonne méthode c'est d'utiliser un insert_iterator construit à partir du std::set qui contiendra le résultat :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    typedef std::set<std::string> string_set;
     
    string_set E, F, G;
     
    // code intense
     
    std::set_intersection(E.begin(), E.end(),
                          F.begin(), F.end(),
                          std::inserter(G, G.begin()));
     
    // Et voila, G = E <inter> F

  12. #12
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    On peut aussi mettre le résultat dans un autre container, qui aura a priori moins d'overhead, comme par exemple un vector, avec un back_inserter.

    Mais, la meilleure solution est sûrement un truc genre :

    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
    template<class It1, class It2>
    bool intersects (It1 b1, It1 e1, It2 b2, It2 e2)
    {
      while (b1 != e1 && b2 != e2)
      {
        if (*b1 < *b2)
        {
          ++b1;
        }
        else if (*b2 < *b1)
        {
          ++b2;
        }
        else 
        {
          return true;
        }
      }
      return false;
    }
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  13. #13
    Alp
    Alp est déconnecté
    Expert confirmé

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    Oui, du moment que ce sont des sets, ça marche.

  14. #14
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Des set, ou des vecteurs triés, ou des listes triées, ou des deques triés, ou des userContainer triés...
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  15. #15
    Alp
    Alp est déconnecté
    Expert confirmé

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    Oui.
    Mais par défaut c'est set.

    A la limite, on peut à coups de traits optimiser l'intersection : si pas trié, on trie (selon le conteneur on trie différemment), puis on appelle ce code.

  16. #16
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    Juste une petite remarque concernant une partie bien précise du code fournis au départ par r0d... que voici
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    // je copie le plus grand set (entre s1 et s2) dans s3
    s3 = ( s1.size()>s2.size() ) ? s1 : s2;
    Dans le sens où, au mieux, l'intersection ne contiendra que l'ensemble du plus petit set, je copierais plutôt le plus petit que le plus grand dans s3..

    Le code deviendrait alors
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    // je copie le plus petit set (entre s1 et s2) dans s3
    s3 = ( s1.size()>s2.size() ) ? s2 : s1;
    à moins, bien sûr, que je n'ai loupé quelque chose sur le fonctionnement de set_intersection (ce qui est toujours possible )
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  17. #17
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 306
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 306
    Billets dans le blog
    2
    Par défaut
    non tu as raison. Mais de toutes façon, ce n'est pas la bonne façon de procéder

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

Discussions similaires

  1. [debutant] Questions sur 1 futur projet
    Par cyrull22 dans le forum XML/XSL et SOAP
    Réponses: 3
    Dernier message: 28/04/2003, 21h49
  2. Quelques questions sur le TWebBrowser...
    Par CorO dans le forum Web & réseau
    Réponses: 3
    Dernier message: 17/01/2003, 21h23
  3. Question sur les handles et les couleurs...
    Par MrDuChnok dans le forum C++Builder
    Réponses: 7
    Dernier message: 29/10/2002, 08h45
  4. Réponses: 2
    Dernier message: 11/08/2002, 21h27
  5. question sur les message box !
    Par krown dans le forum Langage
    Réponses: 7
    Dernier message: 02/08/2002, 16h11

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