AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Diese Funktion schneller machen?

Ein Thema von Pseudemys Nelsoni · begonnen am 9. Dez 2004 · letzter Beitrag vom 9. Dez 2004
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von Pseudemys Nelsoni
Pseudemys Nelsoni

Registriert seit: 24. Dez 2002
Ort: Hamburg-Harburg
3.551 Beiträge
 
#1

Diese Funktion schneller machen?

  Alt 9. Dez 2004, 00:39
ok, diese funktion ist nur ein beispiel, aber viele meiner andere laufen genauso ab...

Delphi-Quellcode:
function fmtstr(const s: string; const c: char): string;
var
  i: integer;
  b: boolean;
begin
  result := ''; b := false;
  for i := 1 to length(s) do
  begin
    if s[i] = c then
    begin
      if (result = '') or (b = true) then
        continue;
      b := true;
    end
    else b := false;
    result := result + s[i];
  end;
  if (result <> '') and (result[length(result)] = c) then
    setstring(result, pchar(result), length(result)-1);
end;
ziel dieser funktion ist es einen string "ordentlich" zu machen, anhand des seperators.... also wenn ich z.b so einen string übergebe:

Zitat:
..hi.bla.....blubb....
wird die funktion:

Zitat:
hi.bla.blubb
zurückgeben.

wenn ich diese funktion 1million mal in einer schleife aufrufe dauert das ganze ca 1,094 sekunden....

gibt es irgendwie eine schnellere methode für diese funktion? es sollten keine funktionen aus der VCL verwendet werden.
Mario
MSN: cyanide@ccode.de
  Mit Zitat antworten Zitat
jbg

Registriert seit: 12. Jun 2002
3.483 Beiträge
 
Delphi 10.1 Berlin Professional
 
#2

Re: Diese Funktion schneller machen?

  Alt 9. Dez 2004, 00:47
Zitat von Pseudemys Nelsoni:
result := result + s[i];
Das kostet auf Dauer sehr viel Rechenzeit, da ein neuer Speicherbereich mit einem Byte mehr reserviert wird, der alte String dort hinein kopiert und das Zeichen angehängt wird. Zusätzlich muss der alte String-Speicher freigegeben werden.
Und dieses Prozedere wird nun 1 Mio mal ausgeführt.
Besser du setzt Result vor der Schleife auf die Worst-Case Länge (in deinem Fall SetLength(Result, Length(S))). Nun kannst du die Zeichen direkt zuweisen "Inc(RealLen);Result[RealLen] := S[i];". Nach dem Schleifendurchlauf setzt du nun mit SetLength(Result, RealLen) die entgültige Länge fest.


Zitat:
Delphi-Quellcode:
  if (result <> '') and (result[length(result)] = c) then
    setstring(result, pchar(result), length(result)-1);
Hätte es nicht auch SetLength(Result, Length(Result) - 1) getan?


Für was brauchst du denn b. Das wird doch gar nicht ausgewertet.
  Mit Zitat antworten Zitat
Benutzerbild von Pseudemys Nelsoni
Pseudemys Nelsoni

Registriert seit: 24. Dez 2002
Ort: Hamburg-Harburg
3.551 Beiträge
 
#3

Re: Diese Funktion schneller machen?

  Alt 9. Dez 2004, 00:59
hallo jbg,

danke für deine antwort, ich werde versuchen es umzusetzen.

b ist true wenn das letzte zeichen der seperator war, so vermeide ich das ein seperator doppelt geschrieben wird.


EDIT:

Delphi-Quellcode:
function fmtstr(const s: string; const c: char): string;
var
  i, len: integer;
  b: boolean;
begin
  Result := '';
  if s <> 'then
  begin
    setlength(result, length(s));
    len := 0; b := false;
    for i := 1 to length(s) do
    begin
      if s[i] = c then
      begin
        if (result[1] = #0) or (b = true) then
          continue;
        b := true;
      end
      else b := false;
      len := len + 1;
      result[len] := s[i];
    end;
    if result[length(result)] = c then
      setlength(result, len-1)
    else setlength(result, len);
  end;
end;
was ist denn hier falsch?

wenn ich das tue:

Zitat:
test := fmtstr('s.u...', '.');
dann ist test "s.u."


wieso ist der punkt am ende noch da?
Mario
MSN: cyanide@ccode.de
  Mit Zitat antworten Zitat
jbg

Registriert seit: 12. Jun 2002
3.483 Beiträge
 
Delphi 10.1 Berlin Professional
 
#4

Re: Diese Funktion schneller machen?

  Alt 9. Dez 2004, 08:47
Zitat:
if (result[1] = #0) or (b = true) then
Das ist nicht dasselbe wie oben. Das Result[1] zeigt dir nicht an, dass der String leer ist. Das kannst du mit "len = 0" prüfen. Und ein "b = true" kann tötlich enden. Lass einfach das "=true" weg. Und bei "b=false" kann man auch schreiben "not b". Beides ist erstens kürzer und auch irgendwie besser erkennbar.

Zitat:
Delphi-Quellcode:
    if result[length(result)] = c then
      setlength(result, len-1)
    else setlength(result, len);
Das Length(Result) ist zu diesem Zeitpunkt ja nicht zwangsläufig das letzte Zeichen. Das steht nämlich in Result[len]. Und du kannst hier die zwei SetLength aufrufe zu einem machen, indem du bei dem TRUE-Code der if-Abfrage einfach Len dekrementierst. Das ist nämlich der einzige Unterschied zum anderen SetLength() Aufruf.
  Mit Zitat antworten Zitat
Benutzerbild von Pseudemys Nelsoni
Pseudemys Nelsoni

Registriert seit: 24. Dez 2002
Ort: Hamburg-Harburg
3.551 Beiträge
 
#5

Re: Diese Funktion schneller machen?

  Alt 9. Dez 2004, 08:51
moin jbg,

habe es nun so:

Delphi-Quellcode:
function fmtstr(const s: string; const c: char): string;
var
  i, len: integer;
  b: boolean;
begin
  if s <> 'then
  begin
    len := 0; b := false;
    setlength(result, length(s));
    result[1] := #0;
    for i := 1 to length(s) do
    begin
      if s[i] = c then
      begin
        if (result[1] = #0) or (b) then
        begin
          b := true;
          continue;
        end;
        b := true;
      end
      else b := false;
      len := len + 1;
      result[len] := s[i];
    end;
    if result[len] = c then
      setlength(result, len-1)
    else setlength(result, len);
  end;
end;
funktioniet einwandfrei, danke nochmal.

was meinst du mit "tödlich" enden? generell meine boolesche variable dort oder das ich "= true" benutzt habe?

btw: kann ich das doppelte "b := true" irgendwie zu einem machen?
Mario
MSN: cyanide@ccode.de
  Mit Zitat antworten Zitat
Robert Marquardt
(Gast)

n/a Beiträge
 
#6

Re: Diese Funktion schneller machen?

  Alt 9. Dez 2004, 09:09
Ich wuerde das letzte Zeichen am Ende einmal pruefen und gegebenenfalls weghauen.
Damit verschwindet dieser unsinnige und unelegante Test mit der booleschen Variablen.
  Mit Zitat antworten Zitat
Benutzerbild von Pseudemys Nelsoni
Pseudemys Nelsoni

Registriert seit: 24. Dez 2002
Ort: Hamburg-Harburg
3.551 Beiträge
 
#7

Re: Diese Funktion schneller machen?

  Alt 9. Dez 2004, 09:20
brauche die variable aber für die mittleren seperatoren, wenn B true ist, dann war das zeichen davor bereits der seperator
Mario
MSN: cyanide@ccode.de
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#8

Re: Diese Funktion schneller machen?

  Alt 9. Dez 2004, 09:55
Moin!

Ich frage mich ob es nicht schneller sein würde, mit Pos ein doppelten Separator zu suchen und wenn man was findet einfach ab da mit der Schleife weiter zu laufen und zu sehen wieviele Separatoren noch kommen. Wenn man in der Schleife einen nicht Separator findet, dann kannst du mit Delete() doch bei der Position von Pos()+1 bis zur aktuellen Stelle die Zeichen löschen und gut. Sollte das nicht schneller gehen als auch noch die Strings in der grossen Schleife durchzugehen. Und mit Pos() klappt es auch, da ein .. nachher nicht mehr zu finden sein sollte.

Nur mal so als Idee...

MfG
Muetze1
  Mit Zitat antworten Zitat
Benutzerbild von jim_raynor
jim_raynor

Registriert seit: 17. Okt 2004
Ort: Berlin
1.251 Beiträge
 
Delphi 5 Standard
 
#9

Re: Diese Funktion schneller machen?

  Alt 9. Dez 2004, 10:22
Zitat von Muetze1:
Sollte das nicht schneller gehen als auch noch die Strings in der grossen Schleife durchzugehen. Und mit Pos() klappt es auch, da ein .. nachher nicht mehr zu finden sein sollte.
Ich bezweifel das ständige Pos aufrufe schneller sind.
1. Ist ein Funktionsaufruf immer "Verhältnismäßig" langsam.
2. geht Pos immer von Anfang den String durch. Macht also viele unnütze Aktionen.
3. Bei Delete ist doch das gleiche Probleme wie viele SetLengths. Es wird jedes mal neuer Speicher angefordert und alter freigegeben. Was insgesamt sicherlich negativ auf die Performance ausschlagen wird.

Einzige Optimierung die mir noch einfallen würde ist, am Anfang alle Separatoren zu überspringen.

Delphi-Quellcode:
var
  Start: Integer;
begin
  Len:=Length(s);
Start:=1;
  while (result[Start]=c) and (Start<Len) do
    inc(Start);
for i := Start to length(s) do
(irgendwie sowas) Dadurch spart man sich das result[1] = #0 im if.

Statt Len := Len+1 benutze inc(Len);

statt immer s[i] und result[len] zu machen könntest du auch einen Pointer (PChar) verwenden, der immer erhöht wird.[/delphi]
Christian Reich
Schaut euch mein X-COM Remake X-Force: Fight For Destiny ( http://www.xforce-online.de ) an.
  Mit Zitat antworten Zitat
Robert Marquardt
(Gast)

n/a Beiträge
 
#10

Re: Diese Funktion schneller machen?

  Alt 9. Dez 2004, 10:29
Wie waere es denn mit
Result := StringReplace(S, Ch + Ch, Ch, [rfReplaceAll]);
Dann muss nur noch auf ein Ch am Ende getestet werden.
  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 05:33 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