AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi Wörter aus Text extrahieren beschleunigen
Thema durchsuchen
Ansicht
Themen-Optionen

Wörter aus Text extrahieren beschleunigen

Ein Thema von kng · begonnen am 2. Sep 2008 · letzter Beitrag vom 3. Sep 2008
Antwort Antwort
Seite 1 von 2  1 2      
kng

Registriert seit: 6. Feb 2008
25 Beiträge
 
#1

Wörter aus Text extrahieren beschleunigen

  Alt 2. Sep 2008, 22:53
Hallo Leute,

Ich habe mir folgende Prozedur geschrieben, welche alle Wörter in einem bestimmten Charset aus einem Text extrahiert.
Delphi-Quellcode:
type
  SetOfChar = Set of Char;

procedure ExtractWords(const AText: string;
                       AMinLength, AMaxLength: Integer;
                       AAllowedChars: SetOfChar;
                       AWords: TStrings);
var
  i, iLength: Integer;
  sWord : string;
begin
   i := 0;
   while i < Length(AText) do
   begin
     Inc(i);
     if AText[i] in AAllowedChars then
     begin
      sWord := '';
      repeat
        sWord := sWord + AText[i];
        Inc(i);
      until not (AText[i] in AAllowedChars);
      iLength := Length(sWord);
      if ((AMinLength = 0) or (iLength >= AMinLength)) and
         ((AMaxLength = 0) or (iLength <= AMaxLength)) then
        AWords.Add(sWord);
     end;
   end;
end;
Funktioniert, aber ist bei großen Texten etwas langsam, hat jemand eine Idee, wie man das ganze bescheunigen bzw. optimieren kann?
  Mit Zitat antworten Zitat
Benutzerbild von Mackhack
Mackhack

Registriert seit: 29. Nov 2003
Ort: San Diego, CA/USA
1.446 Beiträge
 
Delphi 2006 Architect
 
#2

Re: Wörter aus Text extrahieren beschleunigen

  Alt 2. Sep 2008, 23:12
Vlt. durch Pointer und/oder Vermeidung von ueberfluessigen wiederholungen bestimmter Funktionen das ganze zu beschleunigen!
Um etwas Neues zu schaffen muss man seine Ohren vor den Nein-sagern verschliessen um seinen Geist öffnen zu können.
(George Lukas)
  Mit Zitat antworten Zitat
omata

Registriert seit: 26. Aug 2004
Ort: Nebel auf Amrum
3.154 Beiträge
 
Delphi 7 Enterprise
 
#3

Re: Wörter aus Text extrahieren beschleunigen

  Alt 2. Sep 2008, 23:23
Schalte mal bitte deine Bereichsprüfung ein, da knallt und ballert es ja nur so von Fehlermeldungen...

Hier mal eine Korrektur...
Delphi-Quellcode:
procedure ExtractWords(const AText: string;
                       AMinLength, AMaxLength: Integer;
                       AAllowedChars: SetOfChar;
                       AWords: TStrings);
var
  i, iLength, TextLength: Integer;
  sWord : string;
begin
  AWords.BeginUpdate;
  try
    AWords.Clear;
    i := 0;
    TextLength := Length(AText);
    while i < TextLength do
    begin
      Inc(i);
      if AText[i] in AAllowedChars then
      begin
        sWord := '';
        repeat
          sWord := sWord + AText[i];
          Inc(i);
        until (i > TextLength)
              or not (AText[i] in AAllowedChars);
        iLength := Length(sWord);
        if ((AMinLength = 0) or (iLength >= AMinLength))
           and ((AMaxLength = 0) or (iLength <= AMaxLength)) then
        begin
          AWords.Append(sWord);
        end;
      end;
    end;
  finally
    AWords.EndUpdate;
  end;
end;
Ich habe gerade eine 100MB große Datei mit deiner Routine bearbeitet, das hat 7 Sekunden gedauert. Ist das wirklich zu langsam? Wie groß sind den deine Dateien?

Meine Testumgebung...
Delphi-Quellcode:
var Datei:file of char;
    Data:string;
    Start:TDateTime;
    Words:TStringList;
begin
  Words:=TStringList.Create;
  try
    try
      assignfile(Datei, 'test.txt');
      reset(Datei);
      setlength(Data, filesize(Datei));
      BlockRead(Datei, Data[1], filesize(Datei));
    finally
      closefile(Datei);
    end;
    Start:=Now;
    ExtractWords(Data, 0, 0, ['<', 'd', 'i', 'v', '>'], Words);
    ShowMessage(TimeToStr(Now - Start) + ' = Wörter: ' + inttostr(Words.Count));
  finally
    Words.free;
  end;
end;
  Mit Zitat antworten Zitat
alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#4

Re: Wörter aus Text extrahieren beschleunigen

  Alt 3. Sep 2008, 06:03
Erfahrungsgemäß ist die größte Spaß/Performancegrenze (meistens) sowas wie
MyString := MyString + Character Ersetze das durch:
Delphi-Quellcode:
SetLength (MyString, AMaxLength+1);
iLength := 0;
While Text[i] in aAllowedChars Do begin
  inc (iLength);
  MyString[iLength] := Text[i];
  inc(i);
  If (iLength > aMaxLength) and (aMaxLength > 0) Then Break;
  End;
Weiterhin solltest Du deine optimalen Min/Max-Längenangaben anpassen: So benötigst Du immer vier Abfragen, statt 2.
Statt
Delphi-Quellcode:
if ((AMinLength = 0) or (iLength >= AMinLength)) and ((AMaxLength = 0) or (iLength <= AMaxLength)) then
  aWords.Append(aWord);
Am Anfang:
If aMaxLength=0 Then aMaxLength = MaxInt; Und dann
If (iLength>=aMinLength) And (iLength<=aMaxLength) Then aWords.Append(aWord); Auf 'aMinLength=0' musst Du nicht prüfen.

Dann vereinfacht sich die innere Schleife zu:
Delphi-Quellcode:
SetLength (MyString, AMaxLength+1);
iLen := 0;
While (Text[i] in aAllowedChars) And (iLen<=aMaxLength) Do begin
  inc (iLen);
  MyString[iLen] := Text[i];
  inc(i);
End;
So ist dann mein Vorschlag:
Delphi-Quellcode:
procedure ExtractWords(const AText: string; AMinLength, AMaxLength: Integer;
   AAllowedChars: SetOfChar; AWords: TStrings);
var
  i, iLength, TextLength: Integer;
  sWord : string;

begin
  If aMaxLength=0 Then aMaxLength = MaxInt;

  AWords.BeginUpdate;
  try
    AWords.Clear;
    i := 0;
    TextLength := Length(AText);
    while i < TextLength do begin
      Inc(i);
      if Text[i] in aAllowedChars then begin
        SetLength (MyString, AMaxLength+1);
        iLength := 0;
        repeat
          inc (iLength);
          MyString[iLength] := Text[i];
          inc(i);
        until (iLength > aMaxLength) or (not (Text[i] in aAllowedChars))
        if (iLength >= aMinLength) And (iLength <= aMaxLength) Then
          aWords.Append(aWord);
      end;
    end;
  finally
    AWords.EndUpdate;
  end;
end;
Getippt und nicht getestet. Imho gehts noch schneller durch Verwendung von PChar und dynamischen Arrays statt einer TStringList.
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat
kng

Registriert seit: 6. Feb 2008
25 Beiträge
 
#5

Re: Wörter aus Text extrahieren beschleunigen

  Alt 3. Sep 2008, 12:32
Hab die ganze Prozedur jetzt mit einem regulären Ausdruck abgedeckt.
Trotzdem Danke an alle.
  Mit Zitat antworten Zitat
alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#6

Re: Wörter aus Text extrahieren beschleunigen

  Alt 3. Sep 2008, 13:00
Und, wie schnell ist das nun?
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#7

Re: Wörter aus Text extrahieren beschleunigen

  Alt 3. Sep 2008, 13:18
Lade dir von hier http://www.michael-puff.de/Developer...agen_Reddmann/ die Datei Dawg.zip.

Ein DAWG -> Directed Acyclic Word Graph ist eine Wörterdatenbank. Normalerweise benutzt man sie eher um Suchen in großen Wörterdatenbanken sehr effizient durchzuführen zb. Rechtschreibprüfungen, Scrabble Engine, Kreuzworträtsel Solver/Generatoren. Man kann damit auch einen langen Text in dessen Wörter zerlegen. Das geht enorm effizient und ich habe dieses DAWG auch schon für sogenannte Mail-Scanner die in parallel mehrere Text nach Schlagwörtern durchsuchen eingesetzt.

Benutzen kannst du dieses DAWG so:

Delphi-Quellcode:
procedure Test(const Text: String; Strings: TStrings);

  procedure DoPrint(Strings: TStrings; Word: PChar; WordLength: Integer): Boolean; register;
  begin
    Strings.Add(Word);
    Result := False;
  end;

var
  Dawg: TDawg;
begin
  Dawg := TDawg.Create;
  try
    Dawg.Insert(PChar(Text), Length(Text)); // erzeuge Wörterliste aus String als Text

// Alternativen
    Dawg.LoadWordsFromFile('MyFile.txt'); // erzeuge Wörterliste aus Text Datei
    Dawg.LoadWordsFromStream(MyStream); // erzeuge Wörterliste aus TStream
    Dawg.InsertSrings(MyStringList); // erzeuge Wörterliste aus TStrings

// Anzeige der gefundenen Wörter, alphabethisch, in einem TString Object
    Dwag.Enum(@DoPrint, Strings);
  finally
    Dawg.Free;
  end;
end;
Dieses DAWG ist enorm schnell, probier es aus. Eine Textdatei mit 200.000 verschiedenen deutschen Wörtern die 2.54Mb groß ist wird als DWAG, also in alle Wörter zerlegt, in 127ms auf einem P4 1.5Ghz 512Mb Prozessor geladen. Das DWAG enthält danach diese 200.000 Wörter und benötigt 811Kb im Speicher.

Gruß Hagen
  Mit Zitat antworten Zitat
kng

Registriert seit: 6. Feb 2008
25 Beiträge
 
#8

Re: Wörter aus Text extrahieren beschleunigen

  Alt 3. Sep 2008, 13:20
Zitat von alzaimar:
Und, wie schnell ist das nun?
Bei einem Test mit einer 122 MB großen Datei und den Zeichen a-z, A-Z, 0-9 dauerten omata's und deine Prozedur ~ 8 Sekunden.
Mit einem Regulären Ausdruck ~ 3 Sekunden.
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#9

Re: Wörter aus Text extrahieren beschleunigen

  Alt 3. Sep 2008, 13:27
Kannst du irgendwie mal diese 122Mb Datei zur Verfügung stellen, oder aus dem DAWG.zip die mitgeliferte EXE an deiner Datei ausprobieren -> Button "DAWG importieren".

Gruß Hagen
  Mit Zitat antworten Zitat
kng

Registriert seit: 6. Feb 2008
25 Beiträge
 
#10

Re: Wörter aus Text extrahieren beschleunigen

  Alt 3. Sep 2008, 13:32
Zitat von negaH:
Kannst du irgendwie mal diese 122Mb Datei zur Verfügung stellen, oder aus dem DAWG.zip die mitgeliferte EXE an deiner Datei ausprobieren -> Button "DAWG importieren".

Gruß Hagen
Wenn ich das mache, bekomme ich bloß die Meldung "The dawg run out of space.".

//Diese Meldung bekomme ich auch bei Dateien ab 10 MB, wie kann das sein?
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:42 Uhr.
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