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 TstringList sur plusieurs colonnes


Sujet :

Delphi

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2003
    Messages : 439
    Points : 161
    Points
    161
    Par défaut Tri TstringList sur plusieurs colonnes
    Bonjour,

    Mon appli utilise un TStringlist dont voici un extrait:
    ...
    LFPG - 047 NM - 08L - 2134 m - 070°(T)
    LFPG - 047 NM - 26R - 2134 m - 070°(T)
    LFPO - 154 NM - 16 - 3250 m - 210°(T)
    LFPO - 154 NM - 23 - 2650 m - 210°(T)
    LFPB - 047 NM - 07 - 3000 m - 078°(T)
    ...

    Je trie cette liste sur la "colonne" qui contient XXX NM. Mais ce tri me donne:
    ...
    LFPG - 047 NM - 08L - 2134 m - 070°(T)
    LFPB - 047 NM - 07 - 3000 m - 078°(T)
    LFPG - 047 NM - 26R - 2134 m - 070°(T)
    LFPO - 154 NM - 16 - 3250 m - 210°(T)
    LFPO - 154 NM - 23 - 2650 m - 210°(T)
    ...

    J'utilise la fonction CustomSort qui appelle la fonction:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    function CompareInt(List: TStringList; Index1, Index2: Integer): Integer;
    var
    lsStr1, lsStr2: string;
    begin
       lsStr1 := Copy(List[Index1], 8, 3);
       lsStr2 := Copy(List[Index2], 8, 3);
       Result := AnsiCompareText(lsStr1, lsStr2);
    end;
    Je souhaiterais regrouper la première colonne pour obtenir:
    ...
    LFPB - 047 NM - 07 - 3000 m - 078°(T)
    LFPG - 047 NM - 08L - 2134 m - 070°(T)
    LFPG - 047 NM - 26R - 2134 m - 070°(T)
    LFPO - 154 NM - 16 - 3250 m - 210°(T)
    LFPO - 154 NM - 23 - 2650 m - 210°(T)
    ...

    Comment pourrais obtenir le tri souhaiter?

    Merci de votre aide
    Cordialement
    Pierre

  2. #2
    Invité
    Invité(e)
    Par défaut
    Enfaîte tu veux juste un tri par ordre alphabétique, la méthode Sort te donnera ton résultat :
    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
    var
       sl: TStringList;
       i: integer;
    begin
       try
          sl := TStringList.Create;
     
          try
             sl.Add('LFPG - 047 NM - 08L - 2134 m - 070°(T)');
             sl.Add('LFPG - 047 NM - 26R - 2134 m - 070°(T)');
             sl.Add('LFPO - 154 NM - 16 - 3250 m - 210°(T)');
             sl.Add('LFPO - 154 NM - 23 - 2650 m - 210°(T)');
             sl.Add('LFPB - 047 NM - 07 - 3000 m - 078°(T)');
     
             sl.Sort;
     
             for i := 0 to sl.Count - 1 do
                Writeln(sl[i]);
     
             Readln;
          finally
             sl.Free;
          end;
       except
          on E: Exception do
             Writeln(E.ClassName, ': ', E.Message);
       end;
     
    end.

  3. #3
    Membre expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 494
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 494
    Points : 3 129
    Points
    3 129
    Par défaut
    Il faut trier sur plusieurs colonnes en fait.
    Dans la fonction de comparaison, il faut découper les 2 lignes en plusieurs éléments comme tu l'as déjà commencé.
    Ensuite, comparer les valeurs de la première colonne.
    Si elles sont égales, tu compares sur la seconde.
    Si les valeurs de la seconde sont égales, tu compares celles de la troisième.
    etc.

  4. #4
    Membre expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 494
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 494
    Points : 3 129
    Points
    3 129
    Par défaut
    en gros ça donne ça:

    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
     
    uses System.Types, System.StrUtils;
     
    function CompareInt(List: TStringList; Index1, Index2: Integer): Integer;
    var
      A1, A2: TStringDynArray;
      I     : Integer;
    begin
      A1    := SplitString(List[Index1], '-');
      A2    := SplitString(List[Index2], '-');
      for I := Low(A1) to High(A1) do
        if A1[I] <> A2[I] then
        begin
          Result := AnsiCompareText(A1[I], A2[I]);
          Break
        end
        else
          Result := 0;
    end;
     
    procedure TForm20.Button1Click(Sender: TObject);
    var
      sl: TStringList;
      I : Integer;
    begin
      sl := TStringList.Create;
      try
     
        try
          sl.Add('LFPG - 047 NM - 08L - 2134 m - 070°(T)');
          sl.Add('LFPG - 047 NM - 26R - 2134 m - 070°(T)');
          sl.Add('LFPO - 154 NM - 16 - 3250 m - 210°(T)');
          sl.Add('LFPO - 154 NM - 23 - 2650 m - 210°(T)');
          sl.Add('LFPB - 047 NM - 07 - 3000 m - 078°(T)');
     
          sl.CustomSort(CompareInt);
     
          for I := 0 to sl.Count - 1 do
            Memo1.Lines.Add(sl[I]);
     
        except
          on E: Exception do
            Writeln(E.ClassName, ': ', E.Message);
        end;
      finally
        sl.Free;
      end;
     
    end;
    et le résultat est :
    LFPB - 047 NM - 07 - 3000 m - 078°(T)
    LFPG - 047 NM - 08L - 2134 m - 070°(T)
    LFPG - 047 NM - 26R - 2134 m - 070°(T)
    LFPO - 154 NM - 16 - 3250 m - 210°(T)
    LFPO - 154 NM - 23 - 2650 m - 210°(T)

  5. #5
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2003
    Messages : 439
    Points : 161
    Points
    161
    Par défaut
    Merci à tous pour vos réponses,
    Je test ça et reviens vers vous.

    Cordialement
    Pierre

  6. #6
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2003
    Messages : 439
    Points : 161
    Points
    161
    Par défaut
    Citation Envoyé par Papy214 Voir le message
    en gros ça donne ça:

    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
     
    uses System.Types, System.StrUtils;
     
    function CompareInt(List: TStringList; Index1, Index2: Integer): Integer;
    var
      A1, A2: TStringDynArray;
      I     : Integer;
    begin
      A1    := SplitString(List[Index1], '-');
      A2    := SplitString(List[Index2], '-');
      for I := Low(A1) to High(A1) do
        if A1[I] <> A2[I] then
        begin
          Result := AnsiCompareText(A1[I], A2[I]);
          Break
        end
        else
          Result := 0;
    end;
     
    procedure TForm20.Button1Click(Sender: TObject);
    var
      sl: TStringList;
      I : Integer;
    begin
      sl := TStringList.Create;
      try
     
        try
          sl.Add('LFPG - 047 NM - 08L - 2134 m - 070°(T)');
          sl.Add('LFPG - 047 NM - 26R - 2134 m - 070°(T)');
          sl.Add('LFPO - 154 NM - 16 - 3250 m - 210°(T)');
          sl.Add('LFPO - 154 NM - 23 - 2650 m - 210°(T)');
          sl.Add('LFPB - 047 NM - 07 - 3000 m - 078°(T)');
     
          sl.CustomSort(CompareInt);
     
          for I := 0 to sl.Count - 1 do
            Memo1.Lines.Add(sl[I]);
     
        except
          on E: Exception do
            Writeln(E.ClassName, ': ', E.Message);
        end;
      finally
        sl.Free;
      end;
     
    end;
    et le résultat est :
    LFPB - 047 NM - 07 - 3000 m - 078°(T)
    LFPG - 047 NM - 08L - 2134 m - 070°(T)
    LFPG - 047 NM - 26R - 2134 m - 070°(T)
    LFPO - 154 NM - 16 - 3250 m - 210°(T)
    LFPO - 154 NM - 23 - 2650 m - 210°(T)

    J'ai testé ce code, mais il me classe la liste sur la première colonne seulement. (LFPB)
    Mon souhait serait de classer sur la seconde (047 NM) du plus petit au plus grand et ensuite sur la première sans changer le tri précédent.

    Cordialement
    Pierre

  7. #7
    Membre expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    666
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Deux Sèvres (Poitou Charente)

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

    Informations forums :
    Inscription : Novembre 2006
    Messages : 666
    Points : 3 663
    Points
    3 663
    Billets dans le blog
    2
    Par défaut
    Bonsoir,

    Essaye avec la fonction CompareInt écrite de cette manière :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function CompareInt(List: TStringList; Index1, Index2: Integer): Integer;
    var
      A1, A2: TStringDynArray;
      I     : Integer;
    begin
      A1    := SplitString(List[Index1], '-');
      A2    := SplitString(List[Index2], '-');
     
      Result := AnsiCompareText(A1[1]+A1[0],A2[1]+A2[0]);
    end;
    En fait, SplitString renvoie un tableau de chaines de caractères qui correspond au "découpage" de la chaine d'origine en fonction d'un séparateur. Donc le premier élément de ce tableau (indice 0) correspond à la première colonne de ton TStringList (avec le caractère séparateur -), le second élément (indice 1) correspond à la deuxième colonne.
    Donc, pour trier avec pour critère colonne 2 puis colonne 1, on appelle la fonction AnsiCompareText avec colonne 2 et colonne 1 de l'élément 1 et colonne 2 et colonne 1 du second élément. Tu souhaiterais trier sur la 4ème colonne en priorité puis colonne 2 et 1, il faudrait faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    AnsiCompareText(A1[3]+A1[1]+A1[0],A2[3]+A2[1]+A2[0]);
    Ceci est un exemple, il faut bien sur s'assurer que le ième élément soit bien présent dans A1 et A2

  8. #8
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2003
    Messages : 439
    Points : 161
    Points
    161
    Par défaut
    Merci infiniment Gbegreg,

    Ce code me donne exactement ce que je souhaitais.

    Merci également à tous pour votre intérêt.

    Bien cordialement
    Pierre

  9. #9
    Membre expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 494
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 494
    Points : 3 129
    Points
    3 129
    Par défaut
    J'ai testé ce code, mais il me classe la liste sur la première colonne seulement. (LFPB)
    Je ne crois pas non .... vérifie bien ... c'est comme un order by col1, col2, col3, etc.

  10. #10
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par Papy214 Voir le message
    Je ne crois pas non .... vérifie bien ... c'est comme un order by col1, col2, col3, etc.
    Une petite solution avec un TRegex.Split ?

  11. #11
    Membre expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 494
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 494
    Points : 3 129
    Points
    3 129
    Par défaut
    un peu tard à cette heure-ci pour réfléchir mais le TRegex.Split crée aussi un tableau. ça revient au même.

    A1 := TRegex.Split(List[Index1], '\s|\s');


    ça devrait être un truc comme ça. L'avantage, c'est que ça supprime automatiquement le espaces superflus

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

Discussions similaires

  1. Tri JTable sur plusieurs colonnes
    Par laetisam dans le forum Composants
    Réponses: 1
    Dernier message: 30/11/2012, 12h13
  2. Tri Automatique sur plusieurs colonnes
    Par fouinette17 dans le forum Excel
    Réponses: 0
    Dernier message: 20/04/2012, 21h34
  3. [XL-2003] Tri personalisé sur plusieurs colonnes
    Par yorgh1234 dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 14/05/2011, 22h58
  4. [Tableaux] tri sur plusieurs colonnes
    Par melisse dans le forum Langage
    Réponses: 2
    Dernier message: 22/02/2007, 09h51
  5. Tri sur plusieurs colonnes
    Par soso78 dans le forum Access
    Réponses: 2
    Dernier message: 04/03/2006, 15h28

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