Compter les valeurs...

Résolu
cs_fermat Messages postés 2 Date d'inscription vendredi 26 septembre 2003 Statut Membre Dernière intervention 8 avril 2007 - 8 avril 2007 à 19:12
jelume Messages postés 120 Date d'inscription mardi 3 avril 2007 Statut Membre 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.

4 réponses

jelume Messages postés 120 Date d'inscription mardi 3 avril 2007 Statut Membre Dernière intervention 15 novembre 2007 1
8 avril 2007 à 22:02
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;


 
3
japee Messages postés 1727 Date d'inscription vendredi 27 décembre 2002 Statut Modérateur Dernière intervention 6 novembre 2021 8
8 avril 2007 à 21:41
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'
0
japee Messages postés 1727 Date d'inscription vendredi 27 décembre 2002 Statut Modérateur Dernière intervention 6 novembre 2021 8
10 avril 2007 à 00:27
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...
0
jelume Messages postés 120 Date d'inscription mardi 3 avril 2007 Statut Membre Dernière intervention 15 novembre 2007 1
10 avril 2007 à 09:38
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
0
Rejoignez-nous