Compter les valeurs... [Résolu]

Messages postés
2
Date d'inscription
vendredi 26 septembre 2003
Dernière intervention
8 avril 2007
- - Dernière réponse : jelume
Messages postés
122
Date d'inscription
mardi 3 avril 2007
Dernière intervention
15 novembre 2007
- 10 avril 2007 à 09:38
Bonjour,


J'ai un fichier txt.composé de :


10 lignes , comportant 20 valeurs (par ligne), séparées par
un point virgule.


J’ai chargé ce fichier dans un mémo.

Je souhaite établir un tableau dans un second 
mémo , qui affichera le nombre de sorties de chacune d'elles.

Exemple:[408....présent...12 fois]

             
[124....présent...56 fois]


Ma question:

Quelle procédure de calcul faut-il écrire pour obtenir l'affichage dans le 2nd
mémo


Merci de votre aide.
Afficher la suite 

Votre réponse

5 réponses

Meilleure réponse
Messages postés
122
Date d'inscription
mardi 3 avril 2007
Dernière intervention
15 novembre 2007
3
Merci
une autre solution pas très optimisée non plus, mais bon, comme dit japee, il faut encourager les vocations :-)


procedure CompterValeurs(Source: TStrings; Destination: TStrings);
type
  TCompte = record
    Valeur          : Integer;
    NombreOccurences: Integer;
  end;
  TComptes = array of TCompte;


var
  I, J, K: Integer;
  Lst: TStringList;
  Comptes: TComptes;


  function IndiceValeurDansTableau(Value: Integer):Integer;
  var
    I: Integer;
  begin
    Result := -1;
    for I := Low(Comptes) to High(Comptes) do
    begin
      if Value = Comptes[I].Valeur then
      begin
        Result := I;
        Break;
      end;
    end;
  end;


begin


  Destination.Clear;


  // Stockage temporaire pour chaque ligne
  Lst := TStringList.Create;
  for I := 0 to Pred(Source.Count) do  // pour chaque ligne de la source
  begin


    Lst.Clear;
    // Créer un StringList contenant les valeurs séparées par un ;
    ExtractStrings([';'], [' '], PChar(Source[I]), Lst);
    // Trie la liste
    Lst.Sort;


    for J := 0 to Pred(Lst.Count) do
    begin


      // Cherche si la valeur est déjà compteé au moins une fois ou plus
      K := IndiceValeurDansTableau(StrToInt(Lst[J]));


      // Si -1 renvoyé, n'existe pas encore dans le tableau
      if K = -1 then
      begin
        // Ajoute un élément au tableau
        SetLength(Comptes, Length(Comptes) + 1);
        Comptes[High(Comptes)].Valeur           := StrToInt(Lst[J]);
        Comptes[High(Comptes)].NombreOccurences := 1;
      end
      else
        // Incrémente le nombre de valeurs
        Inc(Comptes[K].NombreOccurences);


    end;


  end;
  Lst.Free;


  // A partir de là, pas compliqué
  for I := Low(Comptes) to High(Comptes) do
    Destination.Add(format('%d trouvé %d fois', [Comptes[I].Valeur, Comptes[I].NombreOccurences]));


  Finalize(Comptes);


end;


procedure TForm1.Button1Click(Sender: TObject);
begin
  CompterValeurs(memo1.lines, memo2.lines);
end;


 

Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources 104 internautes nous ont dit merci ce mois-ci

Commenter la réponse de jelume
Messages postés
3830
Date d'inscription
dimanche 12 décembre 2004
Dernière intervention
19 novembre 2018
0
Merci
Tu avait deja pose cette question ici:
http://www.delphifr.com/infomsg_COMPTABILISER-VALEURS-FICHIER-TXT_913762.aspx#3

Ensuite, cherche un peu, ce que tu demandes est très simple. On ne va pas te faire chacune des étapes de ton code.
Commenter la réponse de cptpingu
Messages postés
1799
Date d'inscription
vendredi 27 décembre 2002
Dernière intervention
19 juillet 2018
0
Merci
Salut,

CptPingu a tout à fait raison.

Mais bon, à titre d'encouragement, voici un morceau de code qui fait ce que tu demandes.
Attention, bien que fonctionnel, il mérite d'être optimisé.
Je le mets à ta disposition afin que tu puisses l'étudier.
Si tu a des questions n'hésite pas.

procedure SortAndCountDatas(const StringsA, StringsB: TStrings);
var
  i: Integer;
  StringList: TStringList;
  Tmp: string;
  N: Integer;
begin
  with StringsA do
    for i := 0 to Count -1 do
    begin
      Strings[i] := StringReplace(Strings[i], ';', ',', [rfReplaceAll]);
    end;
  StringList := TStringList.Create;
  try
    StringList.CommaText := StringsA.Text;
    StringList.Sorted := True;
    Form1.Memo3.Text := StringList.Text;
    StringsB.Clear;
    StringsB.BeginUpdate;
    N := 1;
    for i := 0 to StringList.Count -1 do
    begin
      Tmp := StringList[i];
      if (i < StringList.Count -1) and (StringList[i+1] = Tmp) then
        Inc(N)
      else
      begin
        StringsB.Add(Format('%s trouvé %d fois',[Tmp, N]));
        N := 1;
      end;
    end;
    StringsB.EndUpdate;
  finally
    StringList.Free;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Memo1.Lines.LoadFromFile('tonfichier.txt');
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  SortAndCountDatas(Memo1.Lines, Memo2.Lines);
end;

Bonne prog'
Commenter la réponse de japee
Messages postés
1799
Date d'inscription
vendredi 27 décembre 2002
Dernière intervention
19 juillet 2018
0
Merci
Bonsoir,

Je vois que la méthode de jelume a eu plus de succès que la mienne...


Je ne suis pas sûr d'arriver à survivre à ça...


Voici néanmoins une évolution de la mienne.

La fonction ne modifie plus le contenu du premier TStrings, ce qu'elle
n'avait pas à faire puisque ça ne lui était pas demandé, non mais...

procedure SortAndCountDatas(const StringsA, StringsB: TStrings);

var

  i: Integer;

  Tmp: string;

  N: Integer;

begin

  with TStringList.Create do

  try

    Text := StringsA.Text;

    Text := StringReplace(Text, ';', ',', [rfReplaceAll]);

    CommaText := Text;

    Sort;

    StringsB.Clear;

    StringsB.BeginUpdate;

    N := 1;

    for i := 0 to Count -1 do

    begin

      Tmp := Strings[i];

      if (i < Count -1) and (Strings[i+1] = Tmp) then

        Inc(N)

      else

      begin

        StringsB.Add(Format('%s trouvé %d fois', [Tmp, N]));

        N := 1;

      end;

    end;

    StringsB.EndUpdate;

  finally

    Free;

  end;

end;


Bonne nuit les petits, pom pom pom pom, pom pom pom, pom pom...
Commenter la réponse de japee
Messages postés
122
Date d'inscription
mardi 3 avril 2007
Dernière intervention
15 novembre 2007
0
Merci
lol ... désolé japee ... pas taper ...

En fait, je pourrais aussi optimiser la mienne en utilisant une chaine de carctères construite à partir du TStringList original. En remplaçant tous les caratères sLineBreak par un ; et en construisant une liste unique à partir de la propriété text en utilisant extractstrings. Ca évite la double boucle.
Mais j'aime bien aussi ta façon de faire, qui évite d'utiliser un tableau (qui n'a d'autre but que de clarifier le code pour un novice).

Bonne journée

J-Luc
Commenter la réponse de jelume

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.