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 :

Tri de TDateTime et conversion de LongInt en Double


Sujet :

Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2004
    Messages
    540
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 540
    Par défaut Tri de TDateTime et conversion de LongInt en Double
    Bonjour à tous



    Je veux trier par date une liste de fichiers. J'ai utilisé la fonction ci-dessous du site de M. Bardou. Elle trie des LongInt, pas des "double". C'est là le hic.

    Url de la fonction.

    Pour infos, voici la fonction à peine modifiée :
    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
    Var
      Les_Chiffres : array[0..1000000] of longint;
    
    Procedure Tri_Nimportequoi(Longueur_Tab : integer);  // Modifié par moi : j'ai ajouté ce paramètre
    Var
       s, sj, sl, sr, j,S1: LongInt;        // les compteurs intermediaires  du tri
       Code: Longint;                       // Clef de recherche
       Resa_Chiffre: LongInt;               // Utiliser pour les permutation doit etre du mÍme type que la donnée triée
    
       St: Array[0..100, 0..1] Of LongInt;  // Table qui remplace la recursivitÈ et amÈliore CONSIDERABLEMENT les performances
                                            // le dimensionnement ‡ 100 correspond au nombre maximal d'appel en recursivitÈ
                                            // normalement 10 devraient suffir mais avec 100 on doit pouvoir trier quelque milliards d'infos...
    Begin
         S := 1;                            // IMPORTANT je ne trie pas l'ÈlÈment ZERO
         st[S, 0] := 1;                     // Il suffit normalement de metrre S ‡ zero pour le trier
         st[S, 1] := Longueur_Tab;          // Nombre d'elements à trier. Modifié par moi : le paramètre
         Repeat
           sl := st[S, 0];                  // Sauvegarde des offsets pour la recursivitÈ
           sr := st[S, 1];
           S := pred(S);
           Repeat
             j := sl;                       // le quick sort trie le fichier par morceau de plus en plus grands
             sj := sr;
             S1 := (sl + sr) Div 2;            //  on divise le nombre d'elements choisi par deux
             Code := Les_Chiffres[S1];  // On mÈmorise le criter de tri de l'elemnt actif (plus de clarte dans les tests ‡ suivre
             Repeat
               While (Les_Chiffres[J] < Code) Do   // Partant du debut de la portion selectionnée on, recherche le p
                 j := j + 1;                               // premier element plus grand dans cet interval
               While (Code < Les_Chiffres[Sj]) Do  // maintenant on recherchje le plus petit partant de la fin
                 SJ := Sj - 1;
               If j <= sj Then                            // quand on a trouve on permute avec resa_Chiffre
                Begin                                     // l'autre concept du quick sort est que plus la  permutation est
                  Resa_Chiffre := Les_Chiffres[Sj];       // lointaine plus elle est efficace: il vaut mieux permuter le premier
                  Les_Chiffres[Sj] := Les_Chiffres[j];        // avec le dernier que le premier avec le second
                  Les_Chiffres[j] := Resa_Chiffre;    // il a plus de chance d'Ítre ‡ sa place
                  j := Succ(J);                           // Je laisse les mathÈmaticiens le dÈmontrer....
                  sj := Pred(sj);                         // on retrecie la portion de recherche jusqu'a son arrivÈe ‡ 0 elements
                End;
             Until j > sj;
             If j < sr Then                               // Et c'est la qu'on recursive en se servant de la table
               Begin
                 S := Succ(S);
                 St[S, 0] := j;
                 St[S, 1] := sr;
               End;
             sr := sj;
           until sl >= sr;
         Until S < 1;
                                                          // et la c'est FINI
    End;
    Mes types et variables :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    Type
      Struct_Infos_F = record
        Nom_Cplt_F : string;
        Der_Acces : TDateTime;
      End;
     
    Var
      Tab_F : array of Struct_Infos_F;
      Idx_Tab : integer;
      Lst_F : TStringList;
      Nom_F_Liste : string = 'RESULTAT FINAL.LOG';
    Chargement de la StringList et initialisation du tableau :
    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
     
     
    Procedure Charger_Lst_F;
    Var
      i : integer;
     
    begin
      Lst_F := TStringList.Create;
      Lst_F.LoadFromFile(Nom_F_Liste);
      SetLength(Tab_F, Lst_F.Count);
     
      for i := 0 to Lst_F.Count -1 do
        begin
          Tab_F[i].Nom_Cplt_F := Lst_F.Strings[i];
          Tab_F[i].Der_Acces := TimeModificationFichier(Lst_F.Strings[i]);
        end;
     
    end;
    La procédure appelant la fonction de tri :
    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
     
    Procedure Trier_Dates;
    Var
      i : integer;
      Tab_Dates : array of TDateTime;
      Entier_Long : Variant;  // Variant ou LongInt, même résultat
      Lst_ICI : TStringList;
      Num_F : integer;
      Nom_F : string;
     
     
    begin
     
      Lst_ICI := TStringLIst.Create;
      Lst_ICI.Add('FICHIERS TRIES PAR DATES');
      Lst_ICI.Add('------------------------');
     
      for i := 0 to Lst_F.Count -1 do
        begin
          Entier_Long := Tab_F[i].Der_Acces;
          Les_Chiffres[i] := Entier_Long;
        end;
      Tri_Nimportequoi_Bis(Lst_F.Count);
     
      SetLength(Tab_Dates, Lst_F.Count);
      for i := 0 to Lst_F.Count -1 do
         begin
          Idx_Tab := i;
          Num_F := Idx_Tab; // N° de F pointé ds Tab_Dates
          Nom_F := Tab_F[Idx_Tab].Nom_Cplt_F;  // Nom du F pointé ds Tab_F[Idx_Tab]
          Lst_ICI.Add(Nom_F + #13+#10 + 'DATE : ' + DateToStr(Tab_F[Num_F].Der_Acces));
        end;
     
      Lst_ICI.SaveToFile('Z-LISTE TRIEE.TMP');
      Lst_ICI.Free;
      SetLength(Tab_Dates, 0);
     
    end;
    Le tri n'est pas correct, forcément. La fonction de tri opère sur des LongInt, pas des Double. Or, TDateTime est un Double, non ? Et même avec les

    Que feriez-vous ?
    1 - Modifier la fonction elle-même pour la rendre compatible avec des Double ?
    2 - Mieux : convertir en Double les LongInt que sont les TDateTime ? Mais là, je bute. Ce devrait être possible, puisqu'un LongInt est plus court qu'un Double ? L'opération inverse, non.

    Je ne sais pas si j'ai été très clair

  2. #2
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 096
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 096
    Par défaut
    Tu aurais pu le faire avec TStringList.CustomSort qui doit exister depuis au moins Delphi 3

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Lst_F.CustomSort(FichierDateCompare);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    function FichierDateCompare(List: TStringList; Index1, Index2: Integer): Integer;
    begin
      // Le résultat est inférieur à zéro (<0) : Index1 se placera avant Index2 car Index1 est PLUS tard que Index2
      // Le résultat est égal à zéro (=0)      : Index1 est égal à Index2.
      // Le résultat est supérieur à zéro (>0) : Index1 se placera après Index2 car Index2 est PLUS tard que Index1
      // Je veux les plus Fichiers les plus récent en premier
      Result := TimeModificationFichier(List[Index2]) -  TimeModificationFichier(List[Index1]) ;
    end;





    Pour DELPHI 2010 et plus !

    Tu peux aussi utiliser les génériques pour le plaisir de découvrir
    L'avantage c'est que TimeModificationFichier sera appelé nettement moins souvent !

    je te traduits, un code que j'ai écrit pour autre chose, je pense ne pas avoir fait trop d'erreur de copier-remplacer

    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
     
          TFichierDate: record
             Nom_Cplt_F: TFileName;
             Der_Acces : TDateTime;
          end;
     
          TFichierDateOrderer = class(TComparer<TFichierDate>)
          public
            function Compare(const Left, Right: TFichierDate): Integer; override;
          end;
     
    //------------------------------------------------------------------------------
    function TFichierDateOrderer.Compare(const Left, Right: TFichierDate): Integer;
    begin
      // Le résultat est inférieur à zéro (<0) : Left se placera avant Right car Left est PLUS tard que Right
      // Le résultat est égal à zéro (=0)      : Left est égal à Right.
      // Le résultat est supérieur à zéro (>0) : Left se placera après Right car Right est PLUS tard que Left
      // Je veux les plus Fichiers les plus récent en premier
      Result := Right.Der_Acces - Left.Der_Acces ;
    end;
     
     
    ...
    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
     
    var
        Fichiers: record
          Dates: TArray<TFichierDate>;
          DateOrderer: TFichierDateOrderer;
        end;
    begin  
          SetLengh(Fichiers.Dates,  Lst_F.Count );
        for i := 0 to Lst_F.Count -1 do
        begin
          Fichiers.Dates[i].Nom_Cplt_F := Lst_F.Strings[i];
          Fichiers.Dates[i].Der_Acces := TimeModificationFichier(Lst_F.Strings[i]);
        end;
     
     
     
          Fichiers.DateOrderer := TFichierDateOrderer.Create();
            try
              TArray.Sort<TFichierDate>(Fichiers.Dates, Fichiers.DateOrderer);
            finally
              Fichiers.DateOrderer.Free();
            end;
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2004
    Messages
    540
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 540
    Par défaut
    Bonjour

    J'ignorais cette fonction... Hum !

    Je vais potasser ton code. Je m'acheminais vers une conversion LongInt -> double avec une paire de registres.

    Mais : pourquoi TimeModificationFichier est-elle appelée deux fois (ds mon code) ? Une seule, me semblait-il. A l'initialisation du tableau.

  4. #4
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2004
    Messages
    540
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 540
    Par défaut
    Bonjour.

    J'ai besoin d'apprendre ça.

    Déclaration de ta fonction, reprise telle qu'elle :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Function FichierDateCompare(List: TStringList; Index1, Index2: Integer): integer;
    Le code : (en gras, les erreurs signalées par le compilateur) :

    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
    implementation 
    
    ...
    
    Function FichierDateCompare(List: TStringList; Index1, Index2: Integer): integer;
    begin
      // Le résultat est inférieur à zéro (<0) : Index1 se placera avant Index2 car Index1 est PLUS tard que Index2
      // Le résultat est égal à zéro (=0)      : Index1 est égal à Index2.
      // Le résultat est supérieur à zéro (>0) : Index1 se placera après Index2 car Index2 est PLUS tard que Index1
      // Je veux les plus Fichiers les plus récent en premier
      Result := TimeModificationFichier(List[Index2]) -  TimeModificationFichier(List[Index1]) ;  // Types incompatibles integer et extended
    end;
    
    
    
    Procedure Charger_Lst_F;
    Var
      i : integer;
      Idx1, Idx2 : integer;
      Resultat : Extended;
    
    begin
    
      Lst_F := TStringList.Create;
      Lst_F.LoadFromFile(Nom_F_Liste);
    
      for i := 0 to Lst_F.Count -1 do
        begin
          Idx1 := i;
          Idx2 := Idx1 +1;
          Lst_F.CustomSort(FichierDateCompare(Lst_F, Idx1, Idx2)); // Types incompatibles TStringListSortCompare et Integer
        end;
    
    end;

    Où est-ce que je coince, là ?

  5. #5
    Membre émérite
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    410
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 410
    Par défaut
    tu ne doit pas appeler toi même CustomSort, cela permet de définir la procédure utilisée lors du tri


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Lst_F := TStringList.Create;
    Lst_F.CustomSort(FichierDateCompare);
    Lst_F.LoadFromFile(Nom_F_Liste);

  6. #6
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2004
    Messages
    540
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 540
    Par défaut
    Ahhh.. Voilà. Merci :hello:

    La documentation de la fonction, sur le site de Delphi, est assez ambigüe sur ce point.

    Je donne le retour.

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

Discussions similaires

  1. [XL-2007] Question sur les tris est les sous-totaux
    Par Runsh63 dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 03/11/2011, 19h23
  2. Question sur les tris !
    Par Antichoc dans le forum z/OS
    Réponses: 2
    Dernier message: 01/10/2009, 13h30
  3. question sur le tri à bulle
    Par argon dans le forum Algorithmes et structures de données
    Réponses: 16
    Dernier message: 23/09/2006, 17h57
  4. [FORMS 10g] Question sur le TRI
    Par TheNerdPhreak dans le forum Forms
    Réponses: 1
    Dernier message: 10/07/2006, 18h19
  5. Réponses: 17
    Dernier message: 16/12/2005, 09h45

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