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 :

Trier un objet : besoin d aide !


Sujet :

Delphi

  1. #1
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Mai 2012
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2012
    Messages : 26
    Points : 20
    Points
    20
    Par défaut Trier un objet : besoin d aide !
    Bonjour

    Je m initie à delphi et à la programmation objet et j ai du mal avec cette derniere.
    J'ai une liste de valeurs (1,10,8,3) qui sont donc initialement classées 1,2,3 et 4
    à l issue d un tri décroissant, j ai 10,8,3,1 soit d apres les positions initiales 2,3,4,1
    je souhaite faire les differences deux à deux de ces classements c est à dire 1-2, 2-3, 3-4 et 4-1.

    Je suis convaincu qu en declarant un objet nombre avec position initiale et valeur initiale et valeur triee=0 au debut pour tous, puis en faisant un tri sur valeur initiale et en affectant cette nouvelle position à valeur triee je peux y arriver mais je ne sais absolument pas comment faire.

    Pourriez vous svp me montrer comment declarer cet objet et lancer le tri sur valeur initiale s il vous plait car je n ai pas compris du tout comment y parvenir.

    pour l algo de tri il y en a sur le net, donc a priori pas de pb sauf que, à l issue du tri, comment boucler sur le nouveau classement ? Je n ai aucune idee de comment faire etant donné que mes seules valeurs sont valeurs initiale...

    Je sais j en demande un peu beaucoup mais là je seche. Ce n est pas que je n y ai pas reflechi, je suis meme parvenu à le realiser mais sans objet et c est tres lent et c est un bon exemple pour comprendre, à defaut de maitriser l objet.

    donc pour prouver ma bonne foi, voici mon code, pas tres accademique pour la plus part d entre vous mais j ai pas pu faire mieux...


    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
    List_Temp := TStringList.Create;
     
          for j := 0 to List.Count - 1 do
          begin
            if (strtofloat(List[j]) < 10) then
              List_Temp.Add('0' + List[j])
            else
              List_Temp.Add(List[j]);
          end;
          List_Temp.Sort;
          List_vt := TStringList.Create;
          c := 0;
          for j := 0 to List_Temp.Count - 1 do
          begin
            for L := 0 to List_Temp.Count - 1 do
            begin
              if strtofloat(List[j]) = strtofloat(List_Temp[L]) then
              begin
                c := c + 1;
                List_vt.Add(inttostr(L));
                List_Temp[L] := '-1';
                Diff := abs(L - j);
                Diff := Diff * Diff;
                s_diff := s_diff + Diff;
                break;
              end;
            end;
          end;
          List_Temp.destroy;
    merci pour votre aide

    EDIT : Je precise que la finalité est de faire la somme des carres de toutes ces differences de positions. donc si il y a plus simple comme raisonnement, je suis aussi prenneur ;-). merci

  2. #2
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 457
    Points
    28 457
    Par défaut
    Bonjour,

    Alors déjà le TStringList pour gérer des nombres on oubli !

    Soit tu utilises un simple Array, soit tu utilises un TList avec des objets TNombre

    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
     
    procedure TForm1.FormCreate(Sender: TObject);
    const
      n: array[1..4] of Integer = (1,10,8,3);
    var
      v: array[1..4] of Integer;
      o: array[1..4] of Integer;
      i: Integer;
      t: Integer;
      b: Boolean;
    begin
    // ordre initial
      for i := 1 to 4 do
      begin
        v[i] := n[i];
        o[i] := i;
      end;
    // bubble sort, suffisant pour peu de valeurs
      i := 1;
      b := True;
      repeat
        if v[i] < v[i + 1] then
        begin
          t := v[i];
          v[i] := v[i+1];
          v[i+1] := t;
     
          t := o[i];
          o[i] := o[i+1];
          o[i+1] := t;
     
          b := False;
        end;
        Inc(i);
        if (i = 4) and (not b) then
        begin
          i := 1;
          b := True;
        end;
      until i = 4;
    // pour info
      Memo1.Lines.Add(Format('%d, %d, %d, %d', [n[1], n[2], n[3], n[4]]));
      Memo1.Lines.Add(Format('%d, %d, %d, %d', [v[1], v[2], v[3], v[4]]));
      Memo1.Lines.Add(Format('%d, %d, %d, %d', [o[1], o[2], o[3], o[4]]));
    // l'ordre initial est connu !
      Memo1.Lines.Add(Format('1-%d, 2-%d, 3-%d, 4-%d', [o[1], o[2], o[3], o[4]]));
    end;
    et voici l'approche Objet
    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
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
     
    uses
      Contnrs;
     
    type
      TNombre = class
        Index : Integer;
        Valeur: Integer;
        constructor Create(AIndex, AValeur: Integer);
      end;
     
    constructor TNombre.Create(AIndex, AValeur: Integer);
    begin
      Index := AIndex;
      Valeur := AValeur;
    end;
     
    function SortByValue(p1, p2: Pointer): Integer;
    begin
      Result := TNombre(p2).Valeur - TNombre(p1).Valeur;
    end;
     
    procedure TForm1.FormCreate(Sender: TObject);
    const
      n: array[1..4] of Integer = (1,10,8,3);
    var
      Nombres : TObjectList;
      Nombre  : TNombre;
      i: Integer;
      s1, s2, s3: string;
    begin
      Nombres := TObjectList.Create;
      for i := 1 to 4 do
      begin
        Nombre := TNombre.Create(i, n[i]);
        Nombres.Add(Nombre);
      end;
      Nombres.Sort(SortByValue);
    // pour info
      Memo1.Lines.Add(Format('%d, %d, %d, %d', [n[1], n[2], n[3], n[4]]));
      s1 := '';
      s2 := '';
      s3 := '';
      for i := 0 to Nombres.Count - 1 do
      begin
        if i > 0 then
        begin
          s1 := s1 + ', ';
          s2 := s2 + ', ';
          s3 := s3 + ', ';
        end;
        Nombre := TNombre(Nombres[i]);
        s1 := s1 + IntToStr(Nombre.Valeur);
        s2 := s2 + IntToStr(Nombre.Index);
        s3 := s3 + IntToStr(i + 1) + '-' + IntToStr(Nombre.Index);
      end;
      Memo1.Lines.Add(s1);
      Memo1.Lines.Add(s2);
      Memo1.Lines.Add(s3);
      Nombres.Free;
    end;

  3. #3
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Mai 2012
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2012
    Messages : 26
    Points : 20
    Points
    20
    Par défaut
    Merci pour cette réponse qui fonctionne à merveille.

    Je sais que les TstringList pour les nombres, c est pas ça mais c est ce que j ai trouvé de plus simple pour faire ce que j avais à faire.

    par contre j ai encore une question : dans mon exemple j ai pris des integer mais je souhaite passer en double.

    J ai donc modifié les affectation integer en double mais Nombres.Sort(SortByValue); pose un pb.

    j ai pourtant declaré comme suit :

    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
    type
      TNombre = class
        Index: Integer;
        Valeur: double;
        constructor Create(AIndex: Integer; AValeur: double);
      end;
     
    constructor TNombre.Create(AIndex: Integer; AValeur: double);
    begin
      Index := AIndex;
      Valeur := AValeur;
    end;
     
    function SortByValue(p1, p2: Pointer): double;
    begin
      Result := TNombre(p2).Valeur - TNombre(p1).Valeur;
    end;
    je ne comprends pas car SortByValue doit bien retourner un double etant donné que c est la difference de deux doubles non ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    function SortByValue(p1, p2: Pointer): double;
    begin
      Result := TNombre(p2).Valeur - TNombre(p1).Valeur;
    end;
    merci pour ta patience

  4. #4
    Expert éminent sénior
    Avatar de Cl@udius
    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2006
    Messages
    4 878
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Février 2006
    Messages : 4 878
    Points : 10 008
    Points
    10 008
    Par défaut
    Salut
    Citation Envoyé par steph41200 Voir le message
    je ne comprends pas car SortByValue doit bien retourner un double etant donné que c est la difference de deux doubles non ?
    La fonction callback de comparaison doit renvoyer un entier:
    • 0: égalité
    • > 0: Item1 > Item2
    • < 0: Item1 < Item2

    Dans son exemple, Paul se limite à une simple différence puisqu'il manipule des entiers.

    @+ Claudius.

  5. #5
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 879
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 879
    Points : 11 373
    Points
    11 373
    Billets dans le blog
    6
    Par défaut
    on doit pouvoir utiliser Result:=Sign(a-b) pour renvoyer un entier comme attendu

  6. #6
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Mai 2012
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2012
    Messages : 26
    Points : 20
    Points
    20
    Par défaut
    Désolé mais j ai pas compris dumoins...

    Ok la difference de deux entiers est un entier mais si on fait la differe,ce de deux doubles et que l on decalre ce retour en double alors je ne comprends pas que cela pose un pb mais je decouvre... et j ai jamis vu les pointers donc j imagine que cela vient de là non ?

    mais si je retourne simplement 1 si a>b, 0 si a=b et -1 si a<b...

    Quant à Sign...c est si j ai compris http://www.delphibasics.co.uk/Method...ss&Method=Sign c est la même chose non ?

    Merci en tous les cas pour votre aide et votre patience car à 42 ans, l initation, quand on a jamais fait d informatique est plustot hardue...

  7. #7
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 457
    Points
    28 457
    Par défaut
    Citation Envoyé par steph41200 Voir le message
    Désolé mais j ai pas compris dumoins...

    Ok la difference de deux entiers est un entier mais si on fait la differe,ce de deux doubles et que l on decalre ce retour en double alors je ne comprends pas que cela pose un pb mais je decouvre... et j ai jamis vu les pointers donc j imagine que cela vient de là non ?

    mais si je retourne simplement 1 si a>b, 0 si a=b et -1 si a<b...

    Quant à Sign...c est si j ai compris http://www.delphibasics.co.uk/Method...ss&Method=Sign c est la même chose non ?

    Merci en tous les cas pour votre aide et votre patience car à 42 ans, l initation, quand on a jamais fait d informatique est plustot hardue...
    on a le même age, mais j'ai commencé à 15 ans

    en fait la fonction TList.Sort() utilise en paramètre une fonction dont le résultat est un entier dont le signe indique l'ordre des deux éléments en paramètre.

    j'aurais pu écrire ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    function SortByValue(p1, p2: Pointer): Integer;
    begin
      if TNombre(p2).Value > TNombre(p1).Value then
        Result := +1 
      else
      if TNombre(p2).Value < TNombre(p1).Value then
        Result := +1 
      else
        Result := 0;
    end;
    mais comme la fonction de comparaison ne s'intéresse qu'au signe, il est plus performant de simplement faire la différence.

    avec des doubles tu peux aussi faire ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    function SortByValue(p1, p2: Pointer): Integer;
    var
      Delta: Double;
    begin
      Delta := TNombre(p2).Value - TNombre(p1).Value;
      if  Delta <> 0 then
        Delta := Delta / Abs(Delta); // -1 ou +1
      Result := Round(Delta);
    end;

  8. #8
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Mai 2012
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2012
    Messages : 26
    Points : 20
    Points
    20
    Par défaut
    Merci, j ai compris.

    Dans le fond j ai que 27 ans de retard ;-)

    Au rythme où je tourne, pas loin de deux vies et demie pour les rattraper.

    En tous les cas pour un premier post sur ce forum, et pour passer la brosse à reluire à personne, je suis agréablement surpris que des membres ayant ce niveau prennent le temps et soient assez patients pour un novice comme moi.

    Merci

    Edit : une toute petite question performance, un tel code est beaucoup plus rapide avec un objet qu avec des arrays ?

  9. #9
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 879
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 879
    Points : 11 373
    Points
    11 373
    Billets dans le blog
    6
    Par défaut
    le caractère objet ne doit pas en lui-même jouer sur la célérité.

    par contre, la méthode de tri, oui.

    Paul proposait pour ce contexte, un tri à bulle qui n'est pas hyper-véloce, tandis que le TList implémente un Quick Sort, plus rapide, comme son nom l'indique !

    Il existe une poignée d'algos de tris, dont les performances dépendent aussi du volume de données, et parfois de l'ordre des données en entrée (avec certains, il faut quand même un grand nombre d'itérations pour une liste presque triée !)

    Et sur des jeux de données vastes, attention au risque de débordement de pile pour des algos récursifs

  10. #10
    Membre actif
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    549
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 549
    Points : 226
    Points
    226
    Par défaut
    ok merci je comprends mieux maintenant

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

Discussions similaires

  1. Besoin d'aide - Récupérer objet et ses collections
    Par p@radox dans le forum Hibernate
    Réponses: 2
    Dernier message: 09/04/2010, 10h26
  2. [CR11] Besoin d'aide pour trier résultat
    Par Hartdrooz dans le forum Formules
    Réponses: 2
    Dernier message: 21/07/2008, 16h55
  3. [POO] Classe et objet: besoin d'aide
    Par Touareg dans le forum Langage
    Réponses: 4
    Dernier message: 27/02/2007, 17h04

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