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

Delphi Discussion :

Type ENSEMBLE (intersection, soustraction etc)


Sujet :

Delphi

  1. #1
    Inactif  
    Inscrit en
    Février 2004
    Messages
    97
    Détails du profil
    Informations forums :
    Inscription : Février 2004
    Messages : 97
    Points : 53
    Points
    53
    Par défaut Type ENSEMBLE (intersection, soustraction etc)
    J'ai 2 ensembles de données connues et obtenues en tableaux :

    d1[1..200] et d2[1..150]

    Exemple:
    d1[1200,1500,1400,1800........3020]
    d2[4233,1500,3000,1200...]

    Tous les éléments de d2 existent dans d1.
    Mais d2 est moins important en taille.


    Je voudrais trouver et lister les éléments de d2 manquants
    existants dans D1.

    1) quelle solution rationnelle peut-on adopter ?

    2) J'ai pensé aux types "ensemble" de Delphi.
    mais peut-on
    travailler avec des donnée indicées
    (je ne sais pas faire. Les exemples que l'on trouve sur le net
    sont toujours des valeurs "simples : Set of 1..200 et non indicées)

    Merci pour l'aide.

  2. #2
    Expert éminent sénior

    Avatar de sjrd
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Juin 2004
    Messages
    4 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : Suisse

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2004
    Messages : 4 517
    Points : 10 154
    Points
    10 154
    Par défaut
    Les ensembles ne fonctionneront pas, car ils ne peuvent travailler que sur des données scalaires inférieures à 255.

    Voici une méthode pour les tableaux :
    1. Trier les deux tableaux ;
    2. Avancer séquentiellement sur les deux tableaux en même temps, et faire :
    3. Si éléments égaux -> incrémenter les deux index et rien d'autre ;
    4. Si éléments différentes -> enregistrer la valeur du tableau 1, et incrémenter l'index du tableau 1 ;
    5. Répéter les instructions 3 et 4 jusqu'à atteindre le bout des deux tableaux.

  3. #3
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 266
    Points
    3 266
    Par défaut
    Je voudrais trouver et lister les éléments de d2 manquants
    existants dans D1. [Sachant que] Tous les éléments de d2 existent dans d1.
    Mais d2 est moins important en taille
    Moi j'exploiterais plus volontiers les possiblités du type TStringList :
    - placer les données de D1 dans une StringListD1 (avec séquence StringListD1 := TStringList.create; StringListD1.Sorted:=true; StringListD1.Duplicates :=dupIgnore; suivie de StringListD1.add(); voir F1 pour plus de détails sur le type TStringList ),
    - placer les données de D2 dans une StringListD2 (comme fait pour la D1),
    - ensuite on va supprimer dans D1 tout ce que contient D2 et il ne restera dans D1 plus que ce qui manque à D2 et qui existe dans D1 (insn'it?), comme suit par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    procedure TForm1.Elements_De_D2_Manquants_Existants_Dans_D1;
    var           S : string; indiceDe_S_Dans1 : integer;
    begin        for i:=0 to StringListD2.count-1 do
                   begin S:=StringListD2[i];
                           indiceDe_S_Dans1 := StringListD1.IndexOf(S); 
                           StringListD1.Delete(indiceDe_S_Dans1); 
                   end;
                  // et puis, pour voir ce qui reste dans D1 et qui manquait à D2 on peut faire par exemple :
                  memo1.lines.AddStrings(StringListD1);
    end;
    ... et au lieu de faire une procédure on peut aussi transformer celle-ci en une fonction qui renvoie comme Result la StringListD1 ainsi expurgée du contenu de la D2.

  4. #4
    Inactif  
    Inscrit en
    Février 2004
    Messages
    97
    Détails du profil
    Informations forums :
    Inscription : Février 2004
    Messages : 97
    Points : 53
    Points
    53
    Par défaut suite
    Je ne suis pas très familier des StringList.
    Je vais donc m'y coller.

    Merci pour le bout de code (Geyer), c'est parlant.

    Mais s'il y a d'autres idées je suis preneur.

    (J'étais mal parti avec une double boucle sur D1 et D2... croyant faire simple !)

  5. #5
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 950
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 950
    Points : 5 667
    Points
    5 667
    Par défaut
    Kal,
    Citation Envoyé par Gilbert Geyer
    Moi j'exploiterais plus volontiers les possiblités du type TStringList :
    - placer les données de D1 dans une StringListD1 (avec séquence StringListD1 := TStringList.create; StringListD1.Sorted:=true; StringListD1.Duplicates :=dupIgnore; suivie de StringListD1.add(); voir F1 pour plus de détails sur le type TStringList ),
    - placer les données de D2 dans une StringListD2 (comme fait pour la D1),
    - ensuite on va supprimer dans D1 tout ce que contient D2 et il ne restera dans D1 plus que ce qui manque à D2 et qui existe dans D1 (insn'it?), comme suit par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    procedure TForm1.Elements_De_D2_Manquants_Existants_Dans_D1;
    var           S : string; indiceDe_S_Dans1 : integer;
    begin        for i:=0 to StringListD2.count-1 do
                   begin S:=StringListD2[i];
                           indiceDe_S_Dans1 := StringListD1.IndexOf(S); 
                           StringListD1.Delete(indiceDe_S_Dans1); 
                   end;
                  // et puis, pour voir ce qui reste dans D1 et qui manquait à D2 on peut faire par exemple :
                  memo1.lines.AddStrings(StringListD1);
    end;
    ... et au lieu de faire une procédure on peut aussi transformer celle-ci en une fonction qui renvoie comme Result la StringListD1 ainsi expurgée du contenu de la D2.
    Pourquoi se donner la peine de faire des TStringList ?

    La même démarche ira très bien avec des tableaux utilisant directement les valeurs entières en question.

  6. #6
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 266
    Points
    3 266
    Par défaut
    Pourquoi se donner la peine de faire des TStringList ?

    La même démarche ira très bien avec des tableaux utilisant directement les valeurs entières en question.
    1) Tout d'abord il s'agit d'une des démarches parmi lesquelles le demandeur pourra choisir en fonction de ses citères d'appréciation vu que les deux démarches fournissent le même résultat.

    2) Une StringList se shématise comme un tableau que l'on rallonge ou raccourcit de façon aisée.

    3) L'utilisation de StringLists présente les avantages liés à la souplesse d'utilisation de cette structure : StringListD1.Sorted:=true et hop on s'évite la peine d'avoir à s'occuper du tri de tableaux, et avec IndexOf on récupère directement dans une liste l'indice qu'on utilse dans la seconde liste.

    4) De plus comme l'énoncé du problème ne porte que sur un lot de 350 données je pense que s'il est nécessaire de faire 350 fois intToStr(donnee) pour alimenter les StringList cela ne va pas ralentir l'application plus que ne le ferait le tri des deux tableaux initialisés avec des entiers ... sans oublier que l'origine des données peut éventuellement être des string-numériques (on n'a pas vu le reste de l'appli).

    5) Et personnellement j'ai toujours trouvé aux tableaux statiques un côté rigide et s'il me faut un tableau de plus d'une colonne je compare toujours au préalable les avantages/inconvénients qui séparent l'usage d'un tableau dynamique de n colonnes à celui de n StringLists.

    6) Et enfin si cette démarche permet au passage à DURVILLE de se familiariser avec les StringList cela ne fera du mal à personne.

  7. #7
    Expert éminent Avatar de Graffito
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    5 993
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 993
    Points : 7 903
    Points
    7 903
    Par défaut
    Pourquoi se donner la peine de faire des TStringList
    7) Et on peut,via la propriété Objects, associer à chaque ligne un objet.

  8. #8
    Membre éprouvé
    Avatar de CapJack
    Homme Profil pro
    Prof, développeur amateur vaguement éclairé...
    Inscrit en
    Mars 2004
    Messages
    624
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Prof, développeur amateur vaguement éclairé...
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2004
    Messages : 624
    Points : 988
    Points
    988
    Par défaut
    Tu peux utiliser mon unité IntegerList :
    http://www.developpez.net/forums/sho...t=TIntegerList

    Ce sera plus performant qu'avec un TStringList, même si la méthode restera globalement la même..

  9. #9
    Inactif  
    Inscrit en
    Février 2004
    Messages
    97
    Détails du profil
    Informations forums :
    Inscription : Février 2004
    Messages : 97
    Points : 53
    Points
    53
    Par défaut
    Ma question me paraissait basique : comparer 2 ensembles de données numériques.
    Je pensais même qu'elle allait m'attirer les foudres des "pros" ...
    Je vois qu'elle m'a valu des réponses variées (parfois détaillée : Geyer)...
    et que les points de vue sont assez différents ...

    Comme quoi Delphi permet une certaine souplesse et la programmation a toujours des ressorts cachés !

    J'ai élaboré une solution avec tableaux qui me fait rougir parce que assez naïve somme toute (je la mettrai sur le forum sous une forme dépouillée des choses inutiles) ... Elle fonctionne.

    Mais comme je suis curieux je vais expérimenter ce que vous m'avez donné comme pistes.
    Merci... à suivre donc !

  10. #10
    Inactif  
    Inscrit en
    Février 2004
    Messages
    97
    Détails du profil
    Informations forums :
    Inscription : Février 2004
    Messages : 97
    Points : 53
    Points
    53
    Par défaut
    Voici donc la solution (géniale dans sa simplicité !!!)
    que j'emploie pour trouver la différence entre 2 ensembles:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    // 2 listes d'entiers :
    //d1:=[xx,aa,yy....] (n1 = nombre des entiers décrits dans d1)
    //d2:=[xx,yy,ww ...] (n2 = nb dans d2)
    // avec n1>n2
    
    // comparatif : met à rien quand le nombre existe dans les deux listes D1 et D2
     For i:= 1 to n1 do
         for j:= 1 to n2 do if d1[i]=d2[j] then d1[i]:='';
    
    // il reste les non-existants dans la liste D2 que je retrouve en lisant d1 transformé
    
    for i:=1 to n1 do
       if d1[i]<>'' then memo1.Lines.Add (StrToInt(d1[i])) ;

  11. #11
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 266
    Points
    3 266
    Par défaut
    A DURVILLE : Bel esprit de synthèse. Avec tes boucles imbriquées :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    For i:= 1 to n1 do
         for j:= 1 to n2 do if d1[i]=d2[j] then d1[i]:='';
    ... tu t'évites en plus d'avoir à trier les deux tableaux ... au prix de n1xn2 = 200x150 = 30000 tours de boucles. Mais puisque tu utilises d1[i]:=''; j'en déduis que les "2 listes d'entiers" sont en fait 2 listes de "chaines numériques" (sinon t'aurais mis d1[i]:=0;), je te signale qu'en placant ces données directement dans des StringList le nombre de tours de boucles serait descendu à environ 150x(200 div 2) = 15000 en supposant que les éléments de D2 présents dans D1 sont uniformément répartis dans D1 ... par contre seul un chronomètre saura dire si le code en StringListes est plus ou moins rapide que le code en Tableaux.

    Une remarque à propos du bout de code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for i:=1 to n1 do
       if d1[i]<>'' then memo1.Lines.Add (StrToInt(d1[i])) ;
    De deux choses l'une ou bien c'est d1[i]:=''; précité qui est erroné, sinon faut remplacer .Add(StrToInt(d1[i])) par .Add(d1[i]) sinon ta bécane va pas aimer.

  12. #12
    Membre actif
    Profil pro
    DEV
    Inscrit en
    Août 2006
    Messages
    182
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : DEV

    Informations forums :
    Inscription : Août 2006
    Messages : 182
    Points : 211
    Points
    211
    Par défaut
    Et puis un petit Memo1.Lines.Append(...) a la place de Add ne fait pas de mal

    Je chippote je sais

  13. #13
    Inactif  
    Inscrit en
    Février 2004
    Messages
    97
    Détails du profil
    Informations forums :
    Inscription : Février 2004
    Messages : 97
    Points : 53
    Points
    53
    Par défaut
    OK, en voulant faire court je me suis mal fait comprendre :

    d1[i] : c'est un ensemble de string !! et non de numérique.
    Ce qui se déduisait par d1[n]:=''; (chaîne vide)

    donc d1 est défini comme suit : d1 : Array[1..n] of STRING

    Idem pour d2...

    Ceci pour répondre à Geyer qui se donne du mal pour moi !

    Donc ma bécane avale bien la dble boucle ...

    --------------------
    Pour DRAGONHEART :
    Ok pour Append mais le F1 Delphi ne me dit pas trop pourquoi ce choix...

    PS : je ne chipote pas sur l'orthogaffe !

  14. #14
    Expert éminent sénior

    Avatar de sjrd
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Juin 2004
    Messages
    4 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : Suisse

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2004
    Messages : 4 517
    Points : 10 154
    Points
    10 154
    Par défaut
    Citation Envoyé par DragonHeart
    Et puis un petit Memo1.Lines.Append(...) a la place de Add ne fait pas de mal

    Je chippote je sais
    En fait... Si, ça va faire mal Quand j'étais débutant j'utilisais Add sans réfléchir. Quand j'ai commencé à m'intéresser à améliorer l'efficacité de mes programmes, je suis passé à Append. Depuis que j'ose mettre les mains dans le camboui des sources de la VCL, je suis repassé à Add

    En effet le source de Append se résume à un appel à Add Donc est plus lent

Discussions similaires

  1. type ensemble ordonné ?
    Par OutOfRange dans le forum Delphi
    Réponses: 3
    Dernier message: 13/12/2006, 11h46
  2. Pb compilation: type defaults to 'int' etc
    Par vinzzzz dans le forum C
    Réponses: 6
    Dernier message: 31/10/2006, 14h34
  3. [Tableaux] Le type Ensemble existe-t-il ?
    Par petitnuage dans le forum Langage
    Réponses: 3
    Dernier message: 08/06/2006, 20h21

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