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, 12:59
Auch sollte man if ThisByte = 32 then ersetzen durch if Chr(ThisByte) in [' ', #13, #10] then !
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

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

AW: MyGetAverageWordLengthFromFile

  Alt 20. Apr 2016, 13:28
Komm schon .. du bist doch lange genug dabei, um zu wissen, dass man seine Posts 24h lang editieren kann

Variante für nicht-Dateien:
Delphi-Quellcode:
function AvgWordLength(const Text: String): Single;
var
  I: Integer;
  B: Boolean;
  TotalWordCount,
  TotalWordLength: UInt64;
begin
  Result := 0;
  B := false;
  TotalWordCount := 0;
  TotalWordLength := 0;
  for I := Low(Text) to High(Text) do
  begin
    if (not CharInSet(Text[I], [#00..#32, ',', ';', '.', ':'])) then
    begin
      if (not B) then
      begin
        B := true;
        Inc(TotalWordCount);
      end;
      Inc(TotalWordLength);
    end else
    begin
      B := false;
    end;
  end;
  if (TotalWordCount <> 0) then
  begin
    Result := TotalWordLength / TotalWordCount;
  end;
end;
Inklusive folgender Modifikationen:
  1. CharInSet für Unicode Support
  2. UInt64 statt Integer für Strings > 2GiB (sicher ist sicher )

Hier noch meine Version für Dateien:
Delphi-Quellcode:
function AvgWordLength(const Filename: String; MaxLength: UInt64 = 0): Single;
const
  BUFFERSIZE = 1024 * 16;
var
  FS: TFileStream;
  Buffer: array[0..BUFFERSIZE - 1] of AnsiChar; // Replace with AnsiChar for non-unicode files
  BytesRead,
  I: Integer;
  B: Boolean;
  TotalWordCount,
  TotalWordLength: UInt64;
begin
  Result := 0;
  FS := TFileStream.Create(Filename, fmOpenRead);
  try
    B := false;
    TotalWordCount := 0;
    TotalWordLength := 0;
    while (FS.Position < FS.Size) and ((MaxLength = 0) or (FS.Position < MaxLength)) do
    begin
      BytesRead := FS.Read(Buffer[0], BUFFERSIZE * SizeOf(Buffer[0]));
      for I := 0 to BytesRead div SizeOf(Buffer[0]) - 1 do
      begin
        if (not CharInSet(Buffer[I], [#00..#32, ',', ';', '.', ':'])) then
        begin
          if (not B) then
          begin
            B := true;
            Inc(TotalWordCount);
          end;
          Inc(TotalWordLength);
        end else
        begin
          B := false;
        end;
      end;
    end;
  finally
    FS.Free;
  end;
  if (TotalWordCount <> 0) then
  begin
    Result := TotalWordLength / TotalWordCount;
  end;
end;
Inklusive folgender Modifikationen:
  1. Liest Datei Blockweise statt Byteweise aus (stark erhöhte Performance)
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)

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

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

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
 
#4

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
 
#5

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
 
#6

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
 
#7

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
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 06:42 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