cs_fermat
Messages postés2Date d'inscriptionvendredi 26 septembre 2003StatutMembreDernière intervention 8 avril 2007
-
8 avril 2007 à 19:12
jelume
Messages postés120Date d'inscriptionmardi 3 avril 2007StatutMembreDernière intervention15 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
jelume
Messages postés120Date d'inscriptionmardi 3 avril 2007StatutMembreDernière intervention15 novembre 20071 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;
japee
Messages postés1727Date d'inscriptionvendredi 27 décembre 2002StatutModérateurDernière intervention 6 novembre 20218 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;
jelume
Messages postés120Date d'inscriptionmardi 3 avril 2007StatutMembreDernière intervention15 novembre 20071 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).