![]() |
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 ![]() 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:
[edit=Daniel B]Delphi-Tags korrigiert. Mfg, Daniel B[/edit]
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} |
Re: Wörter zählen, optmimieren?
Hi,
ich hab gradmal was versucht...
Delphi-Quellcode:
Das ist wahnsinnig langsam... aber diese version:
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;
Delphi-Quellcode:
ist rasend schnell... bei nem 1mb Text dauert es keine 10tel Sekunde (Also klick auf Button und sofort isses ausgezählt!)
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; Hoffe das hilft dir ein wenig :) Au'revoir, Aya~ |
Re: Wörter zählen, optmimieren?
Zitat:
Danke. :P :lol: |
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 ..
|
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 |
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). |
Re: Wörter zählen, optmimieren?
Hi,
Zitat:
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 |
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. |
Re: Wörter zählen, optmimieren?
[quote="Aya"]Hi,
ich hab gradmal was versucht...
Delphi-Quellcode:
Das ist wahnsinnig langsam... aber diese version:
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;
Delphi-Quellcode:
Hier habe ich aber das Problem, dass auch Leerzeichen mitgezählt werden. Ich habe den Quelltext vollgender Maßen ergänzt:
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;
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); |
Re: Wörter zählen, optmimieren?
Da mußt du aber wegen dem i+1 und der Länge des Strings aufpassen.
|
Re: Wörter zählen, optmimieren?
Bei den Trennzeichen für's "Wörter zählen" sollte man vielleicht auch noch Frage- und Ausrufungszeichen (?!) berücksichtigen :)
Nicht jeder will nur die Wörter im Sourcecode zählen :mrgreen: Bert |
Re: Wörter zählen, optmimieren?
der ansatz die trennzeichen zu zählen ist ja ganz interessant, aber es gibt alle möglichen arten von trennungen, manchmal^würden^menschen sowas sogar zusammenschreiben, was macht man da? sich mal meinen vorschlag anhören :mrgreen:
wörter bilden sich im regelfall aus buchstaben, dafür sind sie bekannt, also warum nicht sobald ein wort anfängt den counter erhöhen und bis zum ende des wortes weitergehen? konkret sähe das folgendermaßen aus...
Delphi-Quellcode:
function WordCount(const S: string): Integer;
const ValidChars = ['a'..'z','A'..'Z','ä','ö','ü','Ä','Ö','Ü','ß']; var P: PChar; begin Result := 0; if S = '' then Exit; P := Pointer(S); repeat if P^ in ValidChars then begin while (P^ in ValidChars) and (P^ <> #0) do Inc(P); Inc(Result); end else Inc(P); until P^ = #0; end; |
Re: Wörter zählen, optmimieren?
@Nothine:
Den Ansatz hatten wir (fast) schon mal weiter oben - ohne die Pointer. Aus Deiner Idee kann noch was werden, wenn Du Deine "ValidChars" noch um Zahlen oder z.B. italienische, spanische oder türkische Buchstaben erweiterst... Aber so im Großen und Ganzen bevorzuge ich doch eher das Parsen nach Trennzeichen :pale: Tschulligung: "Wörter zählen" ist (und bleibt) leider ein Scheiß-Thema, das möglicherweise zu lösen wäre, wenn ... ...wenn es nur eine Sprache gäbe... Komplett naive (realitätsfremde) Grüße daher/dazu von Bert |
Re: Wörter zählen, optmimieren?
Zitat:
Das das langsam sein muß ist ja wohl klar. Gruß Hagen PS: Variablen sind die Freunde des Programmierers ;) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:54 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz