Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Wörter zählen, optmimieren? (https://www.delphipraxis.net/7764-woerter-zaehlen-optmimieren.html)

Baumel 20. Aug 2003 23:10


Wörter zählen, optmimieren?
 
Hallo,
ich möchte die Wörter in einem Rtf-Feld zählen. Dazu habe ich folgenden Code verwendet (s.auch http://www.delphipraxis.net/internal...6rter+z%E4hlen).

Es funktioniert ja eigentlich auch, aber nur unheimlich langsam. Auch die schnellere Variante, die nur auf Leerzeichen prüft, ist bei Texten größer als 100KByte zu langsam (ab 300KByte Text wirds richtig lahm). In Word oder Works gibt es auch so eine Funktion, nur dort ist diese blitzschnell.
Hat jemand Optimierungsvorschläge oder andere meth. Ansätze?
Delphi-Quellcode:
function TEditor.CountWordsSlow(minwordlength:Integer):Integer;
var s: string;
    c: char;
    i, l, le:Integer;
begin
  i:=0;
  le:=Length(Text);
  s:='';
  if le > 0 then
  for l:=1 to le do
  begin
    c:=Text[l];
    if (Upcase(c) in ['A'..'Z','Ä','Ö','Ü','ü','ö','ä','ß']) then s:=s+c
    else
    begin
      if (Length(s) >= minwordlength) Then Inc(i);
      s:='';
    end;
  end;
  CountWordsSlow:=i;
end; {TEditor.CountWords}


function TEditor.CountWordsFast(minwordlength:Integer):Integer;
var s: string;
    c: char;
    pnow, plast,i,l,le:Integer;
begin
  //erste Variante
  (*
  i:=0;
  le:=Length(Text);
  pnow:=1;
  plast:=1;
  if le > 0 then
  for l:=1 to le do
  begin
    if Text[l]=' ' then
    begin
      plast:=pnow;
      pnow:=l;
      if (pnow-plast) > minwordlength then inc(i);
    end;
  end; {for}
  *)
  // zweite Variante
  s:=Text;
  i:=0;
  pnow:=1;
  if Length(s) > 0 then
  while pnow > 0 do
  begin
    pnow:=Pos(' ',s);
    if pnow >= minwordlength then inc(i);
    Delete(s, 1,pnow);
  end;
  //Rest
  CountWordsFast:=i;
end; {TEditor.CountWordsFast}
[edit=Daniel B]Delphi-Tags korrigiert. Mfg, Daniel B[/edit]

Aya 20. Aug 2003 23:18

Re: Wörter zählen, optmimieren?
 
Hi,

ich hab gradmal was versucht...
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  cnt, i: Integer;
begin
  cnt:=0;
  for i:=1 to Length(RichEdit1.Text) do
    if RichEdit1.Text[i] = ' ' then
      Inc(cnt);
  ShowMessage(IntToStr(cnt));
end;
Das ist wahnsinnig langsam... aber diese version:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  S: String;
  cnt, i: Integer;
begin
  cnt:=0;
  S:=RichEdit1.Text;
  for i:=1 to Length(S) do
    if S[i] = ' ' then
      Inc(cnt);
  ShowMessage(IntToStr(cnt));
end;
ist rasend schnell... bei nem 1mb Text dauert es keine 10tel Sekunde (Also klick auf Button und sofort isses ausgezählt!)

Hoffe das hilft dir ein wenig :)

Au'revoir,
Aya~

Baumel 20. Aug 2003 23:42

Re: Wörter zählen, optmimieren?
 
Zitat:

S:=RichEdit1.Text;

Hoffe das hilft dir ein wenig :)
Hmmm, jau. Jetzt gehts ab. Die minimalen Änderungen bei der function CountWordsSlow bringen es. Schwupps das Ergebnis ist sofort da - ohne den Änderungen konnte ich mitunter ca. 15 Minuten Däumchendrehen.


Danke. :P :lol:

JoelH 21. Aug 2003 05:15

hmm,
 
das ist aber arg ungenau ? Wörter könne doch auch durch Kommas etc. getrennt sein oder ?
Ich würd es umgekehrt machen in der abfrage
anstatt
Delphi-Quellcode:
 if s[i] = ' ' then ..
Delphi-Quellcode:
if not(s[i] in ['a'..'z','A'..'Z']) then ..

Chewie 21. Aug 2003 16:42

Re: Wörter zählen, optmimieren?
 
Das ist aber auch blöd. Was, wenn man ein Dollarzeichen schreibt :shock:

Als Trennzeichen dienen i.d.R. Zeilenumbrüche, Leerzeichen, Kommas, Strichpunkte und Tabs
Somit würde das dann etwa so aussehen:

Delphi-Quellcode:
if s[i] in [#9,#10,#13,#32,',','.',';'] then //...

Aufpassen muss man aber bei Trennstrichen vor Zeilenumbrüchen, denn das sind dann meist Silbentrennungszeichen. Befindet sich direkt vor einem Zeilenumbruch ein Minus-Strich(-), trennt der Zeilenumbruch das Wwort nicht.
Die Bedingung also folgendermaßen erweitern:
Delphi-Quellcode:
if s[i] in [#9,#10,#13,#32,',','.',';']) then
  if (s[i] = #13) and (s[i-1] <> '-') then //jetzt ein Wort

JoelH 21. Aug 2003 16:47

hmm,
 
ist allgemein schwierig weil es ist wie mit der deutschen Sprache, es gibt x Ausnahmen und Spezialfälle.
Also ich hab ein wenig Syntaxhighlighting versucht zu machen, gibt auch ein Posting dazu irgendwo hier, wie auch immer. Das parsen ist gar nicht so einfach. Schade dass Delphi keine reg. Expressions von Haus aus unterstützt, das ist einfach eine feine Sache (php,ruby,perl loben muss).

Baumel 21. Aug 2003 16:53

Re: Wörter zählen, optmimieren?
 
Hi,

Zitat:

das ist aber arg ungenau ? Wörter könne doch auch durch Kommas etc. getrennt sein oder ? ...
ich nutze jetzt auch function CountWordsSlow mit der Modifikation, das nicht mehr direkt auf die RTF.Text zugegriffen wird. Der Inhalt wird nun in einen String s kopiert und damit wird dann gearbeitet. Seitdem habe ich keine Performance-Probleme mehr.

Ich dachte anfangs die Performanceeinbußen kamen durch die Mengenoperationen In [...].
Deshalb hatte ich einen anderen, schnelleren (und wie du zurecht bemerkst) äußerst ungenauen Ansatz gewählt (CountWordsFast). Wirklich schneller lief der auch nicht.


Gruß
Dirk

Christian Seehase 21. Aug 2003 16:57

Re: Wörter zählen, optmimieren?
 
Moin Dirk,

bei jeder Art Stringliste, eben auch RichEdit.Lines, wird die Eigenschaft Text bei jedem Lesezugriff auf diese Eigenschaft aus den gesamten Strings zusammengesetzt, und bei jedem Schreibzugriff werden die Zeilen anschliessend neu aufgebaut.
Das ist das, was so auf die Performance drückt.

bjacke 19. Okt 2004 14:55

Re: Wörter zählen, optmimieren?
 
[quote="Aya"]Hi,

ich hab gradmal was versucht...
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  cnt, i: Integer;
begin
  cnt:=0;
  for i:=1 to Length(RichEdit1.Text) do
    if RichEdit1.Text[i] = ' ' then
      Inc(cnt);
  ShowMessage(IntToStr(cnt));
end;
Das ist wahnsinnig langsam... aber diese version:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  S: String;
  cnt, i: Integer;
begin
  cnt:=0;
  S:=RichEdit1.Text;
  for i:=1 to Length(S) do
    if S[i] = ' ' then
      Inc(cnt);
  ShowMessage(IntToStr(cnt));
end;
Hier habe ich aber das Problem, dass auch Leerzeichen mitgezählt werden. Ich habe den Quelltext vollgender Maßen ergänzt:
Delphi-Quellcode:
Var i,count:integer; text:string;
Delphi-Quellcode:
count:=0;
Text:=Rich.Text ;
for i:=1 to length(Text) do
if Text[i]=' ' then if (Text[i+1]<>' ') then inc(count);

LarsMiddendorf 19. Okt 2004 16:15

Re: Wörter zählen, optmimieren?
 
Da mußt du aber wegen dem i+1 und der Länge des Strings aufpassen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:05 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz