Autor |
Beitrag |
galagher
      
Beiträge: 2556
Erhaltene Danke: 45
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: So 16.09.12 19:50
Hallo!
Wie kann ich herausfinden, ob (und wie oft) ein Teilstring innerhalb eines Strings nicht nur vorkommt, sondern, ob und wie oft er auch in einer bestimmten Länge darin vorkommt?
Also zB., wie oft 'Test' im String 'Das ist ein Test zum Testen des Vorkommens eines Teilstrings' vorkommt. Die Funktion Pos würde mir hier 2 liefern, ich suche aber exakt das Wort 'Test', ich brauche eine Lösung, die mir 1 liefert, denn 'Test' ist hier genau nur 1x enthalten, 'Testen' ist ein anderes Wort!
Also so etwas wie:
Delphi-Quelltext 1:
| if PosLen(sSubString, sString) > 1 then |
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
Jann1k
      
Beiträge: 866
Erhaltene Danke: 43
Win 7
TurboDelphi, Visual Studio 2010
|
Verfasst: So 16.09.12 20:47
Du könntest ja nach 'Test ' suchen lassen, problematisch wirds, wenn Satzzeichen dazukommen (wenn man nicht auch 'Test,', 'Test.' etc. suchen will. Ich würde bei jedem Ergebnis, das dir von pos geliefert wird, überprüfen ob an der Stelle nach dem Wort, kein Buchstabe steht, dann erst zählt der Fund.
|
|
HeftCD
      
Beiträge: 91
Erhaltene Danke: 9
Win2k, WinXP, Win7, Win8
Delphi 3 Pro, Delphi 5, Delphi 7, Turbo Delphi, BC1
|
Verfasst: So 16.09.12 20:50
dann mußte Du den String mit einer Schleife durchgehen.
evtl. z.B:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| Vorkommen := 0; i := 0 while i < Length(ZeilesString)-1 do begin inc(i); A := pos(ZeilesString, Suchstring) if A <> 0 then begin inc (Vorkommen); ZeilesString := copy(ZeilesSting,i+length(Suchstring),Length(ZeilesSting)); end; end; |
kurz ohne IDE geschnipselt
|
|
Perlsau
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Mo 17.09.12 15:55
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38:
| FUNCTION StringCount(Zeile, Suchwort : String; Exakt : Boolean) : Integer;
CONST Zeich : Set of Char = [' ', '.', ';', ':', ',', '!', '?', ')', '"', '/', '#','%','+','-','*','\',']','}'];
VAR z, p, L : Integer; EFund, Fund : Boolean; W : Char;
BEGIN L := Length(Suchwort); Result := 0; Fund := TRUE;
WHILE Fund DO BEGIN p := POS(Suchwort,Zeile); Fund := p > 0; IF Fund THEN INC(Result);
IF Fund THEN BEGIN Delete(Zeile, 1, p+L-1);
IF Exakt THEN BEGIN W := Zeile[1]; EFund := W in Zeich; IF NOT EFund THEN DEC(Result); END; END; END; END; |
|
|
galagher 
      
Beiträge: 2556
Erhaltene Danke: 45
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Di 18.09.12 21:02
Hallo!
Vielen Dank für eure Antworten  , aber ich komme im Moment nicht dazu, mir das näher anzusehen!
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
Narses
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Di 18.09.12 22:21
Moin!
Perlsau hat folgendes geschrieben : | Delphi-Quelltext 1: 2: 3:
| FUNCTION StringCount(Zeile, Suchwort : String; Exakt : Boolean) : Integer; Delete(Zeile, 1, p+L-1); | |
 Vielleicht solltest du erwähnen, dass sich dein Vorschlag nur für sehr kurze Strings eignet, da du unnötigerweise den zu durchsuchenden String kopierst und dann auch noch per Delete bearbeitest, was den Heap zumüllt.
Der Standard für eine halbwegs effiziente Suche sollte wohl Boyer-Moore sein.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
Perlsau
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Di 18.09.12 22:29
Narses hat folgendes geschrieben : | Moin!
Vielleicht solltest du erwähnen, dass sich dein Vorschlag nur für sehr kurze Strings eignet, da du unnötigerweise den zu durchsuchenden String kopierst und dann auch noch per Delete bearbeitest, was den Heap zumüllt. |
Wieso nur für sehr kurze Strings? Kann ich nicht nachvollziehen.
Wo kopiere ich deiner Ansicht nach den zu durchsuchenden String?
Was meinst du mit "Heap zumüllen"? Welche Gefahren siehst du durch die Bearbeitung des zu durchsuchenden Strings via Delete?
Narses hat folgendes geschrieben : | Der Standard für eine halbwegs effiziente Suche sollte wohl Boyer-Moore sein. |
Ist das nicht ein wenig zu aufwendig und umständlich?
|
|
Narses
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Di 18.09.12 23:25
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
Perlsau
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Mi 19.09.12 00:05
@Narses: Das begreife ich heute abend wohl nicht mehr ... natürlich stimme ich deinen Argumenten zu, aber ich kann's im Moment wohl nicht besser. Ich kann auch kein C, so daß mir das Programmierbeispiel bei Wikipedia nicht weiterhilft. Aber ich bleibe dran, denn eine ordentlich funktionierende Suchfunktion für lange Texte braucht man immer wieder mal ...
|
|
Gausi
      
Beiträge: 8548
Erhaltene Danke: 477
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Mi 19.09.12 09:43
Wenn man in dem Heuhaufen nur kleine Nadeln sucht (sowas wie "Nadel"), dann bringt Boyer-Moore auch noch nicht fuchtbar viel. Der geht nur dann richtig ab, wenn man längere Dinge sucht.  Wobei natürlich das Delete wirklich eine Bremse ist.
Da gibts aber auch was für Delphi, ich hab da mal was vorbereitet.  Ein paar Boyer-Moore-Varianten sind auch dabei.
_________________ We are, we were and will not be.
Für diesen Beitrag haben gedankt: Mathematiker, Narses
|
|
Nersgatt
      
Beiträge: 1581
Erhaltene Danke: 279
Delphi 10 Seattle Prof.
|
Verfasst: Mi 19.09.12 09:47
_________________ Gruß, Jens
Zuerst ignorieren sie dich, dann lachen sie über dich, dann bekämpfen sie dich und dann gewinnst du. (Mahatma Gandhi)
Für diesen Beitrag haben gedankt: Narses
|
|
jaenicke
      
Beiträge: 19314
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mi 19.09.12 11:14
Um mal ein kleines Beispiel zu bringen wie der gepostete Quelltext zumindest etwas besser aussieht (von den durch die Kürze unlesbaren weil nichtssagenden Variablennamen mal abgesehen): 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35:
| function StringCount(const Zeile, Suchwort: String; const Exakt : Boolean): Integer; const Zeich: set of Char = [' ', '.', ';', ':', ',', '!', '?', ')', '"', '/', '#','%','+','-','*','\',']','}']; var z, p, L: Integer; EFund, Fund: Boolean; W: Char; CurrentRow: PChar; begin L := Length(Suchwort); Result := 0; Fund := True; CurrentRow := PChar(Zeile);
while Fund do begin p := Pos(Suchwort, CurrentRow); Fund := p > 0; if Fund then Inc(Result);
if Fund then begin Inc(CurrentRow, p + L - 1);
if Exakt then begin W := CurrentRow[0]; EFund := W in Zeich; if not EFund then Dec(Result); end; end; end; end; |
|
|
galagher 
      
Beiträge: 2556
Erhaltene Danke: 45
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Mi 19.09.12 18:12
jaenicke hat folgendes geschrieben : | Um mal ein kleines Beispiel zu bringen wie der gepostete Quelltext zumindest etwas besser aussieht (von den durch die Kürze unlesbaren weil nichtssagenden Variablennamen mal abgesehen):function StringCount(const Zeile, Suchwort: String; const Exakt : Boolean): Integer; |
Mit der Version von jaenicke klappt es, vorher hatte ich Zugriffsfehler-Meldungen. Die Dauer ist für meine Zwecke erstmal egal, ich brauche es für mein Projekt, um maximal ein paar KB (meist viel weniger) an Text zu durchsuchen.
Ja, das const hätte ich noch eingebaut! Ich benutze das, wo immer möglich.
Danke!
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
jaenicke
      
Beiträge: 19314
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Do 20.09.12 08:28
galagher hat folgendes geschrieben : | vorher hatte ich Zugriffsfehler-Meldungen |
Das dürfte daran liegen, dass nach dem Weitergehen um soundso viele Zeichen auf das erste Zeichen in CurrentRow zugegriffen wird ohne zu prüfen, ob das Stringende schon erreicht ist. Die Prüfung fehlt auch bei mir, ich wollte nur den Code als Beispiel umstellen (const, Pointer statt Stringoperationen, die unsägliche Turbo Pascal Formatierung weg, ...).
|
|
ml-kuen
      
Beiträge: 17
Win 95, Win 98, Win 2000, Win XP, Win 7
Delphi 7 personal
|
Verfasst: Do 20.09.12 15:37
So weit mir bekannt ist, sind für derartige Aufgaben Reguläre Ausdrücke das Mittel der Wahl. Du selbst hast auch schon einmal einen Beitrag dazu gepostet. Eine Komponente gibts zB. hier: regexpstudio.com/DE/...Expr/Help/About.html
Michael
|
|
Narses
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Do 20.09.12 16:08
Moin!
ml-kuen hat folgendes geschrieben : | So weit mir bekannt ist, sind für derartige Aufgaben Reguläre Ausdrücke das Mittel der Wahl. |
Wenn ich nach Mustern suchen wollte, könnte man darüber nachdenken.  Wenn es aber um konstante (Teil-)Strings geht, würde ich das aus Performance-Gründen bei großen Datenmengen überhaupt nicht empfehlen.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
thepaine91
      
Beiträge: 763
Erhaltene Danke: 27
Win XP, Windows 7, (Linux)
D6, D2010, C#, PHP, Java(Android), HTML/Js
|
Verfasst: Do 20.09.12 19:16
Ich hätte das ganze über "Regular Expression" gelöst. Allerdings muss ich nach kurzer Recherche dazu sagen, das Delphi anscheinend bis "Delphi XE" keine Regex Implementation mitgeliefert hat und somit nur über externe Bibliotheken verwendet werden konnte. Somit ist dieser Ansatz wohl abhängig von deiner Delphi Version.
|
|
jaenicke
      
Beiträge: 19314
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Do 20.09.12 21:42
Davon abgesehen hat ja Narses schon geschrieben wie langsam das ist. Das ist bei dem Funktionsumfang ja auch kein Wunder, macht es aber für einfache Suchen wenig sinnvoll. Ich habe an der Stelle dann auch wieder auf simple Stringoperationen und einen Parser zurückgegriffen nachdem der Editor, in dem nur ein Teil des Highlighting darüber laufen sollte, zu langsam wurde...
|
|
|