Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Effizienteste Datenverarbeitung eines Strings (https://www.delphipraxis.net/163869-effizienteste-datenverarbeitung-eines-strings.html)

hedie 19. Okt 2011 17:59

Effizienteste Datenverarbeitung eines Strings
 
Hallo zusammen

Ich habe folgende String struktur:

<G48.51123,9.71545;G48.51123,9.71545;G48.51123,9.7 1545;G48.51123,9.71545;>

Natürlich um einiges länger...

Nun möchte ich nur die Nummern daraus erhalten

also

48.51123
9.71545
.
.
.

Wie mache ich dies am effizientesten?

< und > signalisieren einen start und ein ende
ein G signalisiert den beginn eines zweier blocks

ein ; signalisiert das ende eines zweier blockes

Danke schonmal

Furtbichler 19. Okt 2011 18:44

AW: Effizienteste Datenverarbeitung eines Strings
 
Am effizientesten?
Code:
start = 1;
wiederhole
  posG = Pos('G', Start);
  Verlasse die Schleife, wenn posG = 0;
  posKomma = Pos(',') ab PosG;
  Zahl1 = TextZwischen(posG + 1, posKomma - 1);
  posSemikolon =Pos(';') ab PosKomma;
  Zahl2 = TextZwischen(posSemikolon + 1, posKomma2 - 1);
  Start = posSemikolon + 1
Das ist aber nicht wirklich am effizientesten, aber dafür am einfachsten zu implementieren. Optimal geht das eigentlich nur mit einer Schleife und ein wenig Fallunterscheidung.

geskill 19. Okt 2011 18:55

AW: Effizienteste Datenverarbeitung eines Strings
 
Ich würde da den sledgehammer rausholen und mit Regulären Ausdrücken arbeiten.

Furtbichler 19. Okt 2011 19:05

AW: Effizienteste Datenverarbeitung eines Strings
 
stümmt.

himitsu 19. Okt 2011 19:06

AW: Effizienteste Datenverarbeitung eines Strings
 
Was verstehst du unter Effizient?
- einfach
- einfach + etwas schneller
- noch schneller (nicht so einfach)

hedie 19. Okt 2011 19:21

AW: Effizienteste Datenverarbeitung eines Strings
 
Danke für eure antworten...


Zitat:

Zitat von himitsu (Beitrag 1131346)
Was verstehst du unter Effizient?
- einfach
- einfach + etwas schneller
- noch schneller (nicht so einfach)

- theoretisch ja noch schneller, aber da es nachvolziehbar sein sollte: einfach + etwas schneller...
es sei den etwas schneller ist zu langsam :)

Es handelt sich um bis zu 128000 Zeichen

Kannst du ein paar beispiele machen oder suchworte liefern?
Danke :)

Zitat:

Zitat von Furtbichler (Beitrag 1131341)
Am effizientesten?
Code:
start = 1;
wiederhole
  posG = Pos('G', Start);
  Verlasse die Schleife, wenn posG = 0;
  posKomma = Pos(',') ab PosG;
  Zahl1 = TextZwischen(posG + 1, posKomma - 1);
  posSemikolon =Pos(';') ab PosKomma;
  Zahl2 = TextZwischen(posSemikolon + 1, posKomma2 - 1);
  Start = posSemikolon + 1
Das ist aber nicht wirklich am effizientesten, aber dafür am einfachsten zu implementieren. Optimal geht das eigentlich nur mit einer Schleife und ein wenig Fallunterscheidung.

Danke... werde ich mal versuchen...

bernau 19. Okt 2011 19:30

AW: Effizienteste Datenverarbeitung eines Strings
 
Ungewünschte Zeichen herausfiltern geht auch mit stringReplace.

Delphi-Quellcode:

begin
  deinString := stringReplace(deinString, '<', '', [rfReplaceAll]);
  deinString := stringReplace(deinString, '>', '', [rfReplaceAll]);
  deinString := stringReplace(deinString, 'G', '', [rfReplaceAll]);
  deinString := stringReplace(deinString, ';', #13+#10, [rfReplaceAll]);
  deinString := stringReplace(deinString, ',', #13+#10, [rfReplaceAll]);
end;

hedie 19. Okt 2011 19:33

AW: Effizienteste Datenverarbeitung eines Strings
 
Zitat:

Zitat von bernau (Beitrag 1131356)
Ungewünschte Zeichen herausfiltern geht auch mit stringReplace.

Delphi-Quellcode:

begin
  deinString := stringReplace(deinString, '<', '', [rfReplaceAll]);
  deinString := stringReplace(deinString, '>', '', [rfReplaceAll]);
  deinString := stringReplace(deinString, 'G', '', [rfReplaceAll]);
  deinString := stringReplace(deinString, ';', #13+#10, [rfReplaceAll]);
  deinString := stringReplace(deinString, ',', #13+#10, [rfReplaceAll]);
end;

Interessanter ansatz....

Das dürfte wohl das schnellste sein :)
Danke! :)

himitsu 19. Okt 2011 20:07

AW: Effizienteste Datenverarbeitung eines Strings
 
StringReplace ist eher sehr langsam ... je länger der String und um so mehr Ersetzungen, um so langsamer wird es.

Aber wenn schon, dann könnte man ";G" in ein "," tauschen, dann noch "<G" und ">" entfernen (Delphi-Referenz durchsuchenDelete) und das Ganze dann als DelimitedText mit "," als Delimiter an eine TStringList übergeben.


Ansonsten würde ich es noch mit PosEx und Copy versuchen.

Bummi 19. Okt 2011 20:18

AW: Effizienteste Datenverarbeitung eines Strings
 
das meine ich könnte relativ flott sein ....

eine Bremse könnte SetLength(a,High(a)+2);
sein, hier gegf. einfach in größeren Blöcken anfordern und eine Zähler mitlaufen lassen ...


Delphi-Quellcode:
  TPointF=Record
    x:Double;
    y:Double;
  End;
  TPointArray=Array of TPointF;
mit


Delphi-Quellcode:
Procedure FillArray(var a:TPointarray;Const s:AnsiString);
var
  s1,s2:AnsiString;
  i,l,x1,x2:Integer;
  isFirst:Boolean;
begin
  s1 := StringOfChar(#0,10);
  s2 := StringOfChar(#0,10);
  x1 := 0;
  x2 := 0;
  i := 1;
  l := Length(s);
  while i<l do
    begin
      if s[i] = 'G' then
        begin
            x1 := 0;
            isFirst := true
            end
      else if s[i] = ',' then
        begin
            x2 := 0;
            isFirst := false;
            inc(x1);
            s1[x1] := #0;
        end
      else if s[i] = ';' then
        begin
            x1 := 0;
            inc(x2);
            s2[x2] := #0;
            SetLength(a,High(a)+2);
            a[High(a)].X  := StrToFloat(s1);
            a[High(a)].Y  := StrToFloat(s2);
        end
      else if s[i] = '.' then
        begin
            if isFirst then
              begin
              inc(x1);
              s1[x1] := AnsiChar(Decimalseparator);
              end
            else
              begin
              inc(x2);
              s2[x2] := AnsiChar(Decimalseparator);
              end;
        end
      else if s[i] in ['0'..'9'] then
            begin

            if isFirst then
              begin
                inc(x1);
                s1[x1] := s[i];
              end
               else
              begin
               inc(x2);
               s2[x2] := s[i];
              end;
            end;

      inc(i);
    end;

end;

himitsu 19. Okt 2011 21:57

AW: Effizienteste Datenverarbeitung eines Strings
 
Falls der String immer genau so aufgebaut ist,
also mit einem Buchstaben beim ersten Wert und mit abschließenden ";", dann ginge auch Folgendes

"<" + "Gxxxx,yyyy;" + "Gxxxx,yyyy;" + ... + ">"

Delphi-Quellcode:
var
  S: String;
  L: TStringList/TStrings;
  i, i2: Integer;

S := '<G48.51123,9.71545;G48.51123,9.71545;G48.51123,9.71545;G48.51123,9.71545;>';
L.Clear;
i := 1;
while True do begin
  i2 := PosEx(',', S, i);
  if i2 = 0 then Break;
  L.Add(Copy(S, i + 2, i2 - i - 2));
  i := PosEx(';', S, i2);
  if i = 0 then Break;
  L.Add(Copy(S, i2 + 1, i - i2 - 1));
end;
Statt dem Zwischenspeichern, in der StringListe, könnte man die beiden Zahlen auch direkt verarbeiten, am Ende der Schleife.

BoolString 19. Okt 2011 22:32

AW: Effizienteste Datenverarbeitung eines Strings
 
Vielleicht auch ein Ansatz, wenn deine Terminus 'Einfachheit' bedeutet, daß du auf möglichst wenig fertige Funktionen (Pos, PosEx, etc.) verzichten willst:

Zahlen aus Strings extrahieren

Nicht der optimalste und hübscheste Code, sollte aber für deine Geschichten funzen.

Jan

Furtbichler 20. Okt 2011 07:05

AW: Effizienteste Datenverarbeitung eines Strings
 
Zitat:

Zitat von himitsu (Beitrag 1131384)
Delphi-Quellcode:
var
  S: String;
  L: TStringList/TStrings;
  i, i2: Integer;

S := '<G48.51123,9.71545;G48.51123,9.71545;G48.51123,9.71545;G48.51123,9.71545;>';
L.Clear;
i := 1;
while True do begin
  i2 := PosEx(',', S, i);
  if i2 = 0 then Break;
  L.Add(Copy(S, i + 2, i2 - i - 2));
  i := PosEx(';', S, i2);
  if i = 0 then Break;
  L.Add(Copy(S, i2 + 1, i - i2 - 1));
end;

Eine gelungene Umsetzung des ersten Vorschlags, nur das auf das Prüfen von 'G' verzichtet wird.

himitsu 20. Okt 2011 08:49

AW: Effizienteste Datenverarbeitung eines Strings
 
Oh, das sah da irgendwie anders aus, hatte mir den Code nicht komplett angesehn.
Pos sah nicht wie PosEx aus (waren ja nur zwei Parameter) und ich hate am Ende einfach (ohne hinzgucken) irgendwo ein Delete erwartet :oops:

Nja, k.A. ob eine RegEx-Prüfung (da sie ja mehr prüfen muß) doch schneller ist ... zumindestens nicht, wenn das RegEx in Delphi geschrieben wäre X'D

Hey, dann war ja gleich der erste Vorschlag so mit das Schnellste, was man wohl mit delphieigenen Mitteln so hinbekommen können würde:thumb:

bernau 20. Okt 2011 08:53

AW: Effizienteste Datenverarbeitung eines Strings
 
Zitat:

Zitat von Furtbichler (Beitrag 1131402)
Eine gelungene Umsetzung des ersten Vorschlags, nur das auf das Prüfen von 'G' verzichtet wird.

Ne.Das "G" wurde nicht vergessen. Er geht davon aus, daß einer Zahl vor einem Komma immer ein G vorangestellt ist. Deshalb in der Copy-Funktion das "+2".

Delphi-Quellcode:
L.Add(Copy(S, i + 2, i2 - i - 2));
Es wird aber nicht auf die kleiner/größer Zeichen geachtet. Zumal die Zeichenfolge mit diesen Zeichen öffter vorkommen kann

Furtbichler 20. Okt 2011 21:22

AW: Effizienteste Datenverarbeitung eines Strings
 
Zitat:

Zitat von bernau (Beitrag 1131417)
Zitat:

Zitat von Furtbichler (Beitrag 1131402)
Eine gelungene Umsetzung des ersten Vorschlags, nur das auf das Prüfen von 'G' verzichtet wird.

Ne.Das "G" wurde nicht vergessen.

Lesen müsste man können. "nur auf DAS PRÜFEN von 'G'..." PRÜFEN! PRÜFEN!
Auf das ---> PRÜFEN <--- wurde verzichtet.

Nix 'vergessen'. hab ich nicht geschrieben und auch nicht gemeint. Klar soweit ;-)

Delphi-Quellcode:
Procedure ProcessInputString (const s: String);
Var
  state : TParserStates; // stWaitForTagOpen, stWaitForGee, stEatFirstNumber stEatSecondNumber;
  number1, number2 : String;
  i : Integer;
 
 
begin
  state := stWaitForTagOpen;
  number1 := '';
  number2 := '';

  For i:=1 to length (s) do
    case state of
      stWaitForTagOpen :
        if s[i] = '<' Then
          state := stWaitForGee
        else
          Raise EParserException.Create('"<" expected');
       stWaitForGee :
        case s[i] of
          'G' : state := stEatFirstNumber;
          '>' : state := stEndOfInput;
          else Raise EParserException.CreateF('">" or "G" expected');
        end;
      stEatFirstNumber :
        if s[i] = ',' Then
          state := stEatSecondNumber
        else
          number1 := number1 + s[i];
      stEatSecondNumber :
        if s[i] = ';' then begin
           state := stWaitForGee;
           ProcessNumbers (number1, number2);
           number1 := '';
           number2 := '';
         end
         else
            number2 := number2 + s[i];
     end;

  if state <>stEndOfInput Then
    Raise EParserError ('Unexpected EOF');
end;
Getippt und nicht getestet.

Sollte eigentlich am Schnellsten sein (ok, mit PChar vielleicht noch schneller), denn es gibt nur eine Schleife und man geht nur 1x von vorne nach hinten.

bernau 21. Okt 2011 08:20

AW: Effizienteste Datenverarbeitung eines Strings
 
Zitat:

Zitat von Furtbichler (Beitrag 1131592)
Lesen müsste man können. "nur auf DAS PRÜFEN von 'G'..." PRÜFEN! PRÜFEN!
Auf das ---> PRÜFEN <--- wurde verzichtet.

Nix 'vergessen'. hab ich nicht geschrieben und auch nicht gemeint. Klar soweit ;-)

Na dann.....

himitsu 21. Okt 2011 08:30

AW: Effizienteste Datenverarbeitung eines Strings
 
Je weniger man prüft, um so schneller geht es. (das ersparrt bestimmt nichmal 'ne halbe Millisekunde :stupid: )

bernau 21. Okt 2011 08:39

AW: Effizienteste Datenverarbeitung eines Strings
 
Die Vergabe der Namen ist köstlich
Delphi-Quellcode:
stEatFirstNumber, stEatSecondNumber
.

Musste mal gesagt werden.


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:29 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