AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Delphi MyGetAverageWordLengthFromFile
Thema durchsuchen
Ansicht
Themen-Optionen

MyGetAverageWordLengthFromFile

Ein Thema von PeterPanino · begonnen am 20. Apr 2016 · letzter Beitrag vom 22. Apr 2016
Antwort Antwort
PeterPanino

Registriert seit: 4. Sep 2004
1.472 Beiträge
 
Delphi 10.4 Sydney
 
#1

AW: MyGetAverageWordLengthFromFile

  Alt 20. Apr 2016, 14:08
Danke für den Code! Heute ist der Tag für Fingerübungen!

Mit deiner Funktion kriege ich aber bei der angehängten Textdatei einen Wert von 1,00, mit meiner Funktion (inkl. Berichtigungen) einen Wert von 9,21!

Hier ist nochmals meine berichtigte Funktion:

Delphi-Quellcode:
function MyGetAverageWordLengthFromFile(const sFile: TFileName; MaxBytesToRead: Integer; const WordBoundaries: string = ' ' + #13 + #10): Single;
var
  fs: TFileStream;
  ReadByte: Integer;
  SpacesCount, WordChars: Integer;
  ThisByte: Byte;
  SpaceRead, WordRead: Boolean;
begin
  Result := -1;
  fs := TFileStream.Create(sFile, fmOpenRead or fmShareDenyNone);
  try
    if MaxBytesToRead > fs.Size then
      MaxBytesToRead := fs.Size;

    SpacesCount := 0;
    WordChars := 0;
    SpaceRead := False;
    WordRead := False;
    for ReadByte := 1 to MaxBytesToRead do
    begin
      fs.Read(ThisByte, 1);
      //CodeSite.Send('ThisByte', IntToStr(ThisByte) + ' ' + Chr(ThisByte));
      //if ThisByte = 32 then
      //if Chr(ThisByte) in WordBoundaries then
      if Pos(Chr(ThisByte), WordBoundaries) > 0 then
      begin
        if WordRead then
        begin
          if not SpaceRead then
            Inc(SpacesCount);
          SpaceRead := True;
        end;
        if ReadByte = MaxBytesToRead then
          Dec(SpacesCount);
      end
      else
      begin
        WordRead := True;
        SpaceRead := False;
        Inc(WordChars);
      end;
    end;
    //CodeSite.Send('SpacesCount', SpacesCount);

    if SpacesCount <> -1 then
      Result := WordChars / (SpacesCount + 1);
  finally
    FreeAndNil(fs);
  end;
end;
Angehängte Dateien
Dateityp: zip test3.zip (294 Bytes, 1x aufgerufen)

Geändert von PeterPanino (20. Apr 2016 um 14:10 Uhr)
  Mit Zitat antworten Zitat
PeterPanino

Registriert seit: 4. Sep 2004
1.472 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: MyGetAverageWordLengthFromFile

  Alt 20. Apr 2016, 14:24
Habe es mit dem Taschenrechner nachgeprüft: 9,21 stimmt!
Mit deiner neuesten Version kriege ich jetzt 6,42.

Geändert von PeterPanino (20. Apr 2016 um 14:26 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#3

AW: MyGetAverageWordLengthFromFile

  Alt 20. Apr 2016, 14:45
Habe es mit dem Taschenrechner nachgeprüft: 9,21 stimmt!
Mit deiner neuesten Version kriege ich jetzt 6,42.
Die deutschen Umlaute liegen im Bereich 128..255, wodurch sie bei meinem Filter als Trennzeichen erkannt wurden. Habe diese Range jetzt auch mal zugelassen, allerdings werden jetzt auch Zeichen wie € als korrekter Buchstabe erkannt.

Um das zu 100% korrekt berechnen zu können, müsste man das verwendete Alphabet der Textdatei kennen. Anders wird es immer nur eine Näherung sein.
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
PeterPanino

Registriert seit: 4. Sep 2004
1.472 Beiträge
 
Delphi 10.4 Sydney
 
#4

AW: MyGetAverageWordLengthFromFile

  Alt 21. Apr 2016, 07:20
Habe es mit dem Taschenrechner nachgeprüft: 9,21 stimmt!
Mit deiner neuesten Version kriege ich jetzt 6,42.
Die deutschen Umlaute liegen im Bereich 128..255, wodurch sie bei meinem Filter als Trennzeichen erkannt wurden. Habe diese Range jetzt auch mal zugelassen, allerdings werden jetzt auch Zeichen wie € als korrekter Buchstabe erkannt.

Um das zu 100% korrekt berechnen zu können, müsste man das verwendete Alphabet der Textdatei kennen. Anders wird es immer nur eine Näherung sein.
Stell dir vor, du zahlst 1 Million Euro auf dein Bankkonto ein und nach einer Woche ist leider nur noch die Hälfte davon da. Als du den Banker zur Rechenschaft ziehst, sagt dieser: "Ja, wir haben jetzt eine neue Banking-Software von Zacherl, die hat eine unheimlich gute Performance ..."
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#5

AW: MyGetAverageWordLengthFromFile

  Alt 21. Apr 2016, 10:11
Stell dir vor, du zahlst 1 Million Euro auf dein Bankkonto ein und nach einer Woche ist leider nur noch die Hälfte davon da. Als du den Banker zur Rechenschaft ziehst, sagt dieser: "Ja, wir haben jetzt eine neue Banking-Software von Zacherl, die hat eine unheimlich gute Performance ..."
Die Performanceoptimierung ist doch gar nicht das Problem, sondern das verwendete Alphabet. Meine Funktion war auf die standard printable-ASCII-Range (#32..#127) ausgerichtet. Das ist für englische Texte perfekt, aber um bei deinem Vergleich zu bleiben, muss eine Bank in Deutschland natürlich auch darauf achten, dass sie den Betrag in € und nicht in $ überweist.

Sprich: Für deutsche Texte muss man die Umlaute mit ins Alphabet aufnehmen, bei französischen Texten, sollte man alle Buchstaben mit Accent oder Circumflex beachten, und so weiter.
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
Amateurprofi

Registriert seit: 17. Nov 2005
Ort: Hamburg
1.087 Beiträge
 
Delphi XE2 Professional
 
#6

AW: MyGetAverageWordLengthFromFile

  Alt 21. Apr 2016, 14:36
Für mich ist keine der bisher gezeigten Versionen überzeugend.

In #1 des TE werden alle Zeichen, die keine Alphazeichen sind als Zeichen eines Wortes angesehen.

In #4 werden immerhin Steuerzeichen und ein paar Interpunktionszeichen als nicht zu Worten gehörend angesehen, was auch nicht wirklich Sinn macht.
Nehmen wir den SourceCode des Autors dieses Beitrags als Beispiel, dann sehen wir auf Anhieb ein Dutzend weitere Zeichen, die offensichtlich in Texten vorkommen aber nicht zu Worten gehören.

Auch die Modifikation "2.UInt64 statt Integer für Strings > 2GiB (sicher ist sicher)" ist überflüssig, denn ein String mag > 2GiB sein, aber die Länge (Anzahl Zeichen) liegt innerhalb des Integerbereiches.
Der Autor selbst läuft ja mit for I := Low(Text) to High(Text) do durch den Text, wobei I als Integer deklariert ist.
Hier wird deutlich, dass als Integer deklarierte Zähler für Zeichen und Worte unter keinen Umständen "überlaufen" können.

Hier ist mein Vorschlag in dem die in der Windows API deklarierte Funktion "IsCharAlpha" benutzt wird um zu Worten gehörende Zeichen zu erkennen.
Auch das ist sicher nicht optimal, denn je nach Definition des Begriffs "Wort" kann diese Prüfung unvollständig sein.

Delphi-Quellcode:
type
   TFileMetrics=Record
      Chars:Integer;
      AlphaChars:Integer;
      ControlChars:Integer;
      Words:Integer;
      AvgWordLen:Single;
   End;

FUNCTION GetFileMetrics(Dsn:String):TFileMetrics;
var List:TStrings; S:String; P,P1:PChar;
begin
   FillChar(Result,SizeOf(Result),0);
   List:=TStringList.Create;
   try
      try
         List.LoadFromFile(Dsn);
         S:=List.Text;
         if S='then Exit;
         P:=PChar(S);
         Result.Chars:=Length(S);
         while P^<>#0 do
            if IsCharAlpha(P^) then begin
               P1:=P;
               while IsCharAlpha(P^) do Inc(P);
               Inc(Result.AlphaChars,P-P1);
               Inc(Result.Words);
            end else begin
               if P^<#32 then Inc(Result.ControlChars);
               Inc(P);
            end;
         if Result.Words>0 then Result.AvgWordLen:=Result.AlphaChars/Result.Words;
      except
         on E:Exception do ShowMessage(E.Message);
      end;
   finally
      List.Free;
   end;
end;

PROCEDURE TMain.Test;
begin
   if OpenDialog.Execute then
      with GetFileMetrics(OpenDialog.FileName) do
         ShowMessage('Worte '+IntToStr(Words)+#13+
                     'Avg Länge '+FloatToStr(AvgWordLen)+#13+
                     'Zeichen '+IntToStr(Chars)+#13+'Davon:'+#13+
                     ' - Kontroll Zeichen '+IntToStr(ControlChars)+#13+
                     ' - Alpha Zeichen '+IntToStr(AlphaChars)+#13+
                     ' - Non Alpha Zeichen '+IntToStr(Chars-AlphaChars-ControlChars));
end;
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#7

AW: MyGetAverageWordLengthFromFile

  Alt 22. Apr 2016, 02:00
Ich kann mich nur wiederholen: Ohne das korrekte Alphabet der Eingabedatei zu kennen, ist es unerheblich, ob man MSDN-Library durchsuchenIsCharAlpha nimmt, oder eigenen Filter verwendet. Am Ende ist es trotzdem nicht perfekt. Warum MSDN-Library durchsuchenIsCharAlpha auch nicht besser ist? Deshalb:

Zitat:
Determines whether a character is an alphabetical character. This determination is based on the semantics of the language selected by the user during setup or through Control Panel.
Viel Spaß auf einem deutschen Windows die Wörter in einer französischen Textdatei zu zählen.

ein String mag > 2GiB sein, aber die Länge (Anzahl Zeichen) liegt innerhalb des Integerbereiches.
Da hast du wohl recht, die Zählervariable habe ich tatsächlich vergessen zu ändern Die Version mit dem FileStream betrifft das allerdings nicht.
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
Antwort Antwort


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 21:45 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