Tri numérique sur ListBox [Résolu]

Messages postés
62
Date d'inscription
lundi 8 novembre 2004
Dernière intervention
25 mai 2013
- 19 déc. 2007 à 15:58 - Dernière réponse :
Messages postés
4229
Date d'inscription
vendredi 23 juillet 2004
Dernière intervention
3 août 2018
- 20 déc. 2007 à 19:06
Existe t'il une possibilité de tri numérique automatique sur une ListBox dont tous les items commencent par des chiffres ?
La fonction sorted ne marche pas car elle classe d'abord tous les chiffres qui commencent par 1 puis tous les chiffres qui commencent par 2 etc. Pas réellement ce que je cherche Hi !
Merci pour l'aide
Gabriel
Afficher la suite 

Votre réponse

34 réponses

Meilleure réponse
Messages postés
4229
Date d'inscription
vendredi 23 juillet 2004
Dernière intervention
3 août 2018
- 19 déc. 2007 à 16:14
3
Merci
Salut,

pour que le trie fonctionne il faut ajouter des zéros devant les chiffres

001
002
011

 
@+
Cirec

<hr siz="" />

Merci Cirec 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 90 internautes ce mois-ci

Commenter la réponse de Cirec
Messages postés
2233
Date d'inscription
mardi 10 décembre 2002
Dernière intervention
15 décembre 2014
- 19 déc. 2007 à 18:56
0
Merci
Tiré de ma fonction, partie oú je traite des doubles/Integers:

Lista étant une TStrings

var i, j, small : Integer;

      for i := 0 to Lista.Count - 2 do       
      begin
          small := i;

          smallVal := StrToFloat(Lista[i]);

          for j := i + 1 to Lista.Count - 1 do 
              if StrToFloat(Lista[j]) < smallVal
              then begin
                small := j;
                smallVal := StrToFloat(Lista[j]);
              end;

        if small <> i                           // Permuter
        then begin
          Str := Lista[i];
          Lista[i] := Lista[small];
          Lista[small] := Str;
        end;

Tu dois juste remplacer StrToFloat() par une fonction qui te renvoie l' integer de l'item!!!
A+
Commenter la réponse de cs_MAURICIO
Messages postés
2233
Date d'inscription
mardi 10 décembre 2002
Dernière intervention
15 décembre 2014
- 19 déc. 2007 à 19:04
0
Merci
Une autre façon serait de trier avant de passer les items dans ta liste.
Pour cela, tu peux passer par un Record et un Array:

type
  monRecord=Record
    Valeur: Integer;  // Valeur qui permettra de trouver le plus petit
    MaString; // String qui sera passée dans ta listBox
    Passé: Boolean;  // permet de savoir si on l' a déjá passé dans le listbox
  end;

Tu déclares un aArray comm suit:
Array_Items: Array of monRecord;

Ensuite tu remplies Array_Items avec les différents Items. (N' oublie pas le SetLength de l' array).
"Passé" devra être initialisé à false bien sûr ...

Enfin, tu cherches dans l' array le plus petit (oú Passé = "false") et tu le passes dans ta ListBox.
N' oublie pas de mettre "Passé" à True.

A+
Commenter la réponse de cs_MAURICIO
Messages postés
4229
Date d'inscription
vendredi 23 juillet 2004
Dernière intervention
3 août 2018
- 19 déc. 2007 à 19:52
0
Merci
@Mauricio:

Ta méthode ne fonctionne que si les Items sont que des chiffres !!!!

Si ses Items contiennent aussi des lettres ... dans ce cas ça plante

Il dit bien "tous les items commencent par des chiffres"
ce qui sous-entend qu'ils contiennent aussi des lettres

Du coup il est plus facile de rajouter des zéros devant

ps : toutes les méthodes de tries réagissent de la même manière ...
donc pour obtenir un résultat correcte il faut ajouter des zéros

 
@+
Cirec

<hr siz="" />
Commenter la réponse de Cirec
Messages postés
2233
Date d'inscription
mardi 10 décembre 2002
Dernière intervention
15 décembre 2014
- 19 déc. 2007 à 22:28
0
Merci
Dans ma derniere phrase de mon 1er commentaire j' ai écrit:
"Tu dois juste remplacer StrToFloat() par une fonction qui te renvoie l' integer de l'item!!!"

Mon 2eme commentaire fonctionnerait aussi très bien ...

A+
Commenter la réponse de cs_MAURICIO
Messages postés
4229
Date d'inscription
vendredi 23 juillet 2004
Dernière intervention
3 août 2018
- 19 déc. 2007 à 22:52
0
Merci
Pourquoi faire simple quand on peut faire compliqué

J'avais bien lu ton message
et j'ai même fait les testes qui s'imposent

StrToInt (par exemple) te renvoie une belle exception si la chaine contient des lettres !

ce qui implique qu'il faudrait créer une fonction qui récupère que les chiffres ... mais le trie ne sera pas juste puisque les lettres ne seront pas prise en compte !!!!

Alors que le simple fait d'ajouter des zéros en début permet d'utiliser la méthode de trie interne et sans code supplémentaire avec un résultat trier correctement jusqu'au dernier caractère

 
@+
Cirec

<hr siz="" />
Commenter la réponse de Cirec
Messages postés
4996
Date d'inscription
dimanche 26 février 2006
Dernière intervention
27 mars 2018
- 19 déc. 2007 à 23:04
0
Merci
çà me fait penser au coup du gars qui veut se faire un diaporama avec ses photos de vacances avec un logiciel tout fait..(photo1, photo2..photo12 etc etc)
et surprise lorsqu'il le lance tout est mélangé !
Alors que si bien sur il se dit tiens j'en ai 999 (il en raté une..) et il nomme ses fichiers :
photo001, photo002, photo047..photo238...photo999.
et là ca va nettement mieux..

cantador
Commenter la réponse de cs_cantador
Messages postés
2684
Date d'inscription
jeudi 15 janvier 2004
Dernière intervention
26 juillet 2018
- 20 déc. 2007 à 00:26
0
Merci
Salut,

« Qu'il y ait des gens beaucoup plus savants que d'autres n'est pas très intriguant. Ce qui est extraordinaire, et diablement instructif, c'est à quel point deux personnes ayant des connaissances proches peuvent diverger dans la façon dont elles les interprètent. »

C'est vachement enrichissant les gars !  ;)
Commenter la réponse de Caribensila
Messages postés
1799
Date d'inscription
vendredi 27 décembre 2002
Dernière intervention
19 juillet 2018
- 20 déc. 2007 à 09:20
0
Merci
Quelle que soit la manière dont on va traiter le problème, dans tous les cas, il va bien falloir une routine pour récupérer le nombre qui se trouve en début d'item et qui détermine le classement de la liste.
Commenter la réponse de japee
Messages postés
4229
Date d'inscription
vendredi 23 juillet 2004
Dernière intervention
3 août 2018
- 20 déc. 2007 à 09:46
0
Merci
@Caribensila:
Le problème n'est pas là ... peut importe de quel manière on interprète la chose ... ce que je soulignai c'est qu'il n'est pas utile de réécrire ce qui existe déjà !!! (la fonction de trie)

@Japee:
Pas forcément ... on peut le prévoir à l'avance

Soit c'est l'utilisateur qui les rentre dans ce cas on utilise un MaskEdit

Soit c'est le programmeur qui les rentre dans ce cas c'est à lui de les mettre

Il ne reste plus que la machine c'est le seul cas ou il faudrait écrire du code

ça ne fait que 1 cas sur 3 

Et en plus dans méthode de ce type (ou l'on extrait que les chiffres pour le trie) le résultat risque de ne pas être correcte

01 dca
01 cda
01 acd

Penses tu que le résultat sera correcte

Avec la méthode interne on obtiendrait :
01 acd

01 cda

01 dca

sans réécrire la procédure de trie

 
@+
Cirec

<hr siz="" />
Commenter la réponse de Cirec
Messages postés
2233
Date d'inscription
mardi 10 décembre 2002
Dernière intervention
15 décembre 2014
- 20 déc. 2007 à 10:13
0
Merci
Salut Cirec,
ta méthode est bonne puisque le chiffre est en début de string.
Par contre s' il était à la fin,il y aurait un chtit problème...

C' est pour cela qu' en utilisant un Array de type Record on peut ordonner de la manière que l' on veut, même sans montrer les chiffres dans la listBox.

C' est vrai que c' est plus complexe mais serait 100% réutilisable et cela permet aussi d' ordonner avec d' autres critères que du plus petit au plus grand...

A+
Commenter la réponse de cs_MAURICIO
Messages postés
4229
Date d'inscription
vendredi 23 juillet 2004
Dernière intervention
3 août 2018
- 20 déc. 2007 à 10:45
0
Merci
Salut Mauricio:

il faut que je regarde ça de plus près ...
ou j'ai loupé un truc ou j'y ai rien compris.

Mais jusqu'à preuve du contraire une chaine '123 abc'

avec n'importe quel StrTo... provoque une erreur de conversion ... non ?

et c'est là que je ne comprend pas ta logique :
 Puisque même si tu arrives à extraire les chiffres le trie ne se fera que sur les chiffres et non sur l'ensemble des caractères

En attendant que je teste le code je vous offre une fonction qui ajoute les zéros manquants (uniquement devant)

Uses StrUtils;
Function LeadingZero(Const S : String;
Const Len : Integer = 3): String ;
Var PbS : PByte;
    Cnt : Integer;

Begin
  PbS : = PByte(S);

  SetLength(Result, Length(S));
  Result := S;
  Cnt := 0;
   While (PbS^ > 47)
And (PbS^ < 58)
Do Begin
    Inc(PbS);
    Inc(Cnt);

  End;
  If
(Cnt > 0) And
(Cnt < Len) Then Begin

    Cnt : = ABS(Len - Cnt);
    SetLength(Result, Length(S) +
Cnt);
    Result := DupeString('0', Cnt) + S;

  End ;

End;
<center>Highlighted with Pas2HTML

</center>Utilisation :
S : String = '12 String';

LeagingZero(S)       renvoie '012 String'
LeagingZero(S, 5)   renvoie '00012 String'

LeagingZero(S, 2)   renvoie '12 String'

 
@+
Cirec

<hr siz="" />
Commenter la réponse de Cirec
Messages postés
2233
Date d'inscription
mardi 10 décembre 2002
Dernière intervention
15 décembre 2014
- 20 déc. 2007 à 11:45
0
Merci
Bonjour à tous:

Ça méritait une source de démonstration :
http://www.delphifr.com/codes/TRI-DANS-LISTBOX-COMBOBOX-TSTRINGS_45139.aspx

Il y a les 2 méthodes et une fonction qui permet de récupérer un Integer dans une String (au début de celle-ci ou à la fin).

Comme vous pourrez le voir, la 2ème méthode est bien plus professionnelle, plus rapide, plus personalisable dans le sens oú l' on peut ordonner suivant un ou plusieurs critères de tri, et surtout ne dépend pas du texte que l' on veut passer dans la ListBox.

A+
Commenter la réponse de cs_MAURICIO
Messages postés
4229
Date d'inscription
vendredi 23 juillet 2004
Dernière intervention
3 août 2018
- 20 déc. 2007 à 12:32
0
Merci
C'est bien ce que je disais

ton code ne fonctionne que si les données sont uniques ...

{ Voici le contenu de la ListBox
1 zdhr
2 acabd
1 dbdgh
1 abc
11
aabccd
2 aabccd
111 dkfjgu
}
Procedure SortList(Lista : TStrings);
Var i, j, small, smallVal : Integer;
    Str :
String;
    {Function que j'ai ajouté pour récupérer l'integer}
    Function MyStrToInt(S : String): Integer;
    Var

      PbC : PChar;
      TmpStr : String;
    Begin

      PbC := PChar(S);
      TmpStr := '';
       While (PbC^
In #48..#57) And (PbC^ <>
#0) Do Begin

        TmpStr : = TmpStr + PbC^;
        Inc(PbC);

      End;
      Result :=
StrToInt(TmpStr);
     End ;
Begin
  For i : = 0To Lista.Count - 2Do
  Begin
      small := i;

      smallVal := MyStrToInt(Lista[i]);

       For j : = i + 1To Lista.Count - 1Do
          If MyStrToInt(Lista[j]) <
smallVal
          Then Begin

            small := j;
            smallVal :=
MyStrToInt(Lista[j]);
           End ;

    If small <> i // Permuter
    Then
Begin
      Str : = Lista[i];
      Lista[i] := Lista[small];

      Lista[small] := Str;
     End ;

  End;
End;

Procedure
TFprincipe.Button7Click(Sender: TObject);
Begin
  SortList(ListBox1.Items);
End;
Qui donne un résultat incorrecte :
1 zdhr
1 dbdgh
1 abc
2 acabd
2 aabccd
11
aabccd
111 dkfjgu

Voici ma solution
Procedure
TFprincipe.Button8Click(Sender: TObject);
Var I : Integer;
Begin

  For I : = 0To
ListBox1.Items.Count - 1Do
    ListBox1.Items[I] :=
LeadingZero(ListBox1.Items[I], 4);

  ListBox1.Sorted := True;
End ;

Court simple et éfficace !!!!
<center>Highlighted with Pas2HTML </center>Qui donne un résultat correcte:
001 abc
001 dbdgh
001 zdhr
002 aabccd
002 acabd
011
aabccd
111 dkfjgu

Voilà et si tu veux tester avec ton code Change ceci:

  ARRAY_ADD_ITEM(35,  ' Mon item de valeur 35');
  ARRAY_ADD_ITEM(18,  ' Mon item de valeur 18');
  ARRAY_ADD_ITEM(25,  ' Mon item de valeur 25');
  ARRAY_ADD_ITEM(3,   ' Mon item de valeur 3');
  ARRAY_ADD_ITEM(999, ' Mon 2 item de valeur 999');
  ARRAY_ADD_ITEM(999, ' Mon 1 item de valeur 999');
  ARRAY_ADD_ITEM(-6,  ' Mon item de valeur -6');

 
@+
Cirec

<hr siz ="" />
Commenter la réponse de Cirec
Messages postés
2233
Date d'inscription
mardi 10 décembre 2002
Dernière intervention
15 décembre 2014
- 20 déc. 2007 à 12:49
0
Merci
"C'est bien ce que je disais
ton code ne fonctionne que si les données sont uniques ...

{ Voici le contenu de la ListBox
1 zdhr
2 acabd
1 dbdgh
1 abc
11 aabccd
2 aabccd
111 dkfjgu
}"

Désolé Cirec, mais si tu testes ma source avec ces éléments lá, mes 2 méthodes fonctionnent très bien (c' est la 3ème fois que je te dis que ça marche) ...

A+
Commenter la réponse de cs_MAURICIO
Messages postés
2233
Date d'inscription
mardi 10 décembre 2002
Dernière intervention
15 décembre 2014
- 20 déc. 2007 à 12:58
0
Merci
Tu utilises mal la fonction :
  ARRAY_ADD_ITEM(999, ' Mon

2



item de valeur 999');
  ARRAY_ADD_ITEM(999, ' Mon

1



item de valeur 999');

Doit être écrit: 
  ARRAY_ADD_ITEM(2, ' Mon item de valeur 2');
  ARRAY_ADD_ITEM(1, ' Mon item de valeur 1');

ou même : 
  ARRAY_ADD_ITEM(2, ' Mon item de valeur deux');
  ARRAY_ADD_ITEM(1, ' Mon item de valeur un');
Commenter la réponse de cs_MAURICIO
Messages postés
4229
Date d'inscription
vendredi 23 juillet 2004
Dernière intervention
3 août 2018
- 20 déc. 2007 à 13:07
0
Merci
Je ne vois pas ce qu'il y a de juste la dedans !!!!!!!


En rouge c'est le résultat que tu devrais obtenir


Alors ... ou ça marche !!!!!


Et non j'utilise pas mal ta fonction

C'est justement là ou je voulais en venir
Si j'ai mis 1 et 2 dans le texte avec 999 pour les deux c'est que justement la méthode de trie devrait en tenir compte (ce qu'elle ne fait pas)


Si tes chiffres sont unique alors oui ta méthode fonctionne

Mais si il y a des doublons dans les chiffres ... c'est la pagaille
 
@+
Cirec

<hr siz="" />
Commenter la réponse de Cirec
Messages postés
4229
Date d'inscription
vendredi 23 juillet 2004
Dernière intervention
3 août 2018
- 20 déc. 2007 à 13:10
0
Merci
Vois plus loin que juste les chiffres du début

un trie se fait sur l'ensemble des données si les premières sont identiques

 
@+
Cirec

<hr siz="" />
Commenter la réponse de Cirec
Messages postés
62
Date d'inscription
lundi 8 novembre 2004
Dernière intervention
25 mai 2013
- 20 déc. 2007 à 13:21
0
Merci
Bjr à tous.
Ne vous battez pas pour si peu !
J'avais bien trouvé la méthode de Cirec consistant à mettre tous le nombres au même format à 3 chiffres mais celà devenait contraignant pour les utilisateurs qui saisissent le contenu des items dans une boite de dialogue.
Chaque item est composé de plusieurs champs séparés par des tabulations, le premier champ étant un nombre de longueur quelconque.
WORD possède une possibilité de tri numérique sur ce type de texte en "tableau" et je m'imaginais qu'il y avait peut-être la même possibilité de tri numérique en Delphi sur une ListBox constituée de la même façon.
Je vais prendre mon courage à deux mains.
Bonne journée à tous
gabriel
Commenter la réponse de cs_f6dqm1
Messages postés
2233
Date d'inscription
mardi 10 décembre 2002
Dernière intervention
15 décembre 2014
- 20 déc. 2007 à 13:23
0
Merci
Bem c' est sûr que ça marche pas, il faut reparamétrer la fonction pour tenir compte d' un autre paramètre qui est le texte (qui pourrait être du texte ou un autre integer d' ailleurs dans ma fonction), elle tient compte que de l'integer dans l' exemple.

Il faut juste adapter ici:
        else  // *** Ici on compare des integers, mais on peut comparer tout ce que l' on veut *** //
          if Array_Items[i].Value < Array_Items[RESULT].Value
          then RESULT := i;            // Nouveau item plus petit trouvé !!!

Je vois que tu veux à tout prix avoir raison alors que ta fonction ne fonctionne pas si les chiffres sont à la fin et ainsi, tu imposes le visuel de chaque élément.
A+
Commenter la réponse de cs_MAURICIO

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.